diff --git a/www/.env.example b/.env.example
similarity index 100%
rename from www/.env.example
rename to .env.example
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
index e245ee255..f000c8320 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -1,6 +1,6 @@
---
name: Feature request
-about: Suggest an idea for Firetable
+about: Suggest an idea for Rowy
title: ''
labels: ''
assignees: ''
diff --git a/.github/workflows/tweet_release.yml b/.github/workflows/tweet_release.yml
index ab8f17747..e6a78507a 100644
--- a/.github/workflows/tweet_release.yml
+++ b/.github/workflows/tweet_release.yml
@@ -31,7 +31,7 @@ on:
with:
message:
"Testing github action for tweeting new releases and updates to
- Firetable project"
+ Rowy project"
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
@@ -52,4 +52,4 @@ jobs:
with:
message:
"Testing github action for tweeting new releases and updates to
- Firetable project"
+ Rowy project"
diff --git a/.gitignore b/.gitignore
index 886b2753c..da2408813 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,26 +2,17 @@
# dependencies
/node_modules
-www/node_modules
-
-
-Firetable/node_modules
-cloud_functions/functions/node_modules
/.pnp
.pnp.js
-# testing
-/coverage
-
# production
-www/build
+/build
cloud_functions/functions/lib
-
-# cloud function config
-cloud_functions/functions/src/functionConfig.ts
-
-cloud_functions/functions/firebase-credentials.json
+# firebase
+*.firebaserc
+*-firebase.json
+.firebase/
# misc
.DS_Store
@@ -34,16 +25,5 @@ yarn-debug.log*
yarn-error.log*
firebase-debug.log*
-*.firebaserc
-
-
-# Accidental package installs to root directories
-/yarn.lock
-/package.json
-package-lock.json
-node_modules/
-
-cloud_functions/functions/src/functionConfig.json
-*.iml
-.idea
-*-firebase.json
+.eslintcache
+.npm
diff --git a/.opensource/project.json b/.opensource/project.json
index c9d1fe2af..faa2b212c 100644
--- a/.opensource/project.json
+++ b/.opensource/project.json
@@ -1,5 +1,5 @@
{
- "name": "Firetable",
+ "name": "Rowy",
"platforms": ["Node", "Admin", "Web"],
"content": "README.md",
"related": ["firebase/firebase-js-sdk"],
diff --git a/.prettierrc b/.prettierrc
index ece5d88f3..efe063ef2 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -1,4 +1,4 @@
{
- "trailingComma": "es5",
- "proseWrap": "always"
+ "trailingComma": "es5",
+ "proseWrap": "always"
}
diff --git a/cloud_functions/functions/.yarn/releases/yarn-1.22.5.cjs b/.yarn/releases/yarn-1.22.5.cjs
similarity index 100%
rename from cloud_functions/functions/.yarn/releases/yarn-1.22.5.cjs
rename to .yarn/releases/yarn-1.22.5.cjs
diff --git a/cloud_functions/functions/.yarnrc b/.yarnrc
similarity index 100%
rename from cloud_functions/functions/.yarnrc
rename to .yarnrc
diff --git a/LICENSE b/LICENSE
index a07a7a50a..1d0e1c139 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,201 +1,201 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright 2019 Antler Innovation Pte Ltd
-
- Licensed 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.
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed 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.
diff --git a/README.md b/README.md
deleted file mode 100644
index dc87887d8..000000000
--- a/README.md
+++ /dev/null
@@ -1,170 +0,0 @@
-
- Firetable
-
-
-
- Firetable is an open-source platform to unlock the full potential of Google Firestore
-
-
-
- With Firetable, non-technical team members can access Firestore data with a permission controlled intuitive UI while developers can build fast on the GCP stack (manage their data models, create and deploy cloud functions, connect to third party apps via webhooks and APIs...and more!) 🚀
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-# Features
-
-- **Intuitive spreadsheet like interface for Firestore.** With Firetable UI you
- can view and directly edit the data in Firestore but not just that, you can
- completely manage your existing data model or create from scratch.
-
- - CRUD operations on your data - Add, edit, and delete rows
- - Create table collections, add column fields
- - Sort and filter data
- - Resize and rename columns
-
-- **Rich set of data fields.**
- [29+ field types](https://github.com/FiretableProject/firetable/wiki/Field-Types)
- supported and growing
-
- - Basic types: Short Text, Long Text, Email, Phone, URL…
- - Custom UI pickers: Date, Checkbox, Single Select, Multi Select…
- - Uploaders: Image, File
- - Rich Editors: JSON, Code, Rich Text (HTML)
-
-- **Permission controlled views.** You can customize who sees what data and what
- action they can take with powerful set of access controls based on custom user
- roles.
- [Read more](https://github.com/FiretableProject/firetable/wiki/Role-Based-Security-Rules)
-- **Bulk data actions.** You can import and export your Firestore data from/to
- CSV files.
-
-- **Supercharge your database with your own scripts.**
-
- - Action field: trigger any Cloud Function
- - Derivative field: populate cell with value derived from the rest of the
- row’s values
- - Aggregate field: populate cell with value aggregated from the row’s
- sub-table
-
-- **Integrations with external services.**
- - Connect Table uses Algolia to get a snapshot of another table’s row values
- - Connect Service uses any HTTP endpoint to get a cell value
-
-## Firetable makes it easy to use key Firebase products
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-# Getting started
-
-To set up Firetable, you must be comfortable with working with the command line.
-
-You must have at least a basic understanding of how to use npm and install npm
-packages globally.
-
-We’ve created the Firetable CLI to automate the steps required to set up
-Firetable.
-
-### [**Read the getting started guide →**](https://github.com/FiretableProject/firetable/wiki/Getting-Started)
-
-# Documentation
-
-We’re still working on improving our documentation and writing more
-beginner-friendly guides.
-
-[**Documentation on GitHub Wiki →**](https://github.com/FiretableProject/firetable/wiki)
-
-# Issues
-
-[![Open issues](https://badgen.net/github/open-issues/FiretableProject/firetable)](https://github.com/antlervc/firetable/issues)
-
-[Create issues and bug reports here.](https://github.com/antlervc/firetable/issues)
-Make sure to provide console log outputs and screenshots!
-
-# Roadmap and feature requests
-
-- [Roadmap](https://github.com/FiretableProject/firetable/wiki/Roadmap)
-- [View our ideas and feature requests](https://github.com/FiretableProject/firetable/projects/1)
-
----
-
-
-
-# Contributing 🙌
-
-We welcome any contributions from the open source community.
-
-- **[Good First Issues](https://github.com/FiretableProject/firetable/projects/3)**
- project is a good place to start for contributing to Firetable.
-- For new feature or enhancement, please create an issue first or send us a
- message on **[Discord](https://discord.gg/B8yAD5PDX4)** so that we can discuss
- and guide you as needed ahead of you starting the work.
diff --git a/cloud_functions/firebase.json b/cloud_functions/firebase.json
deleted file mode 100644
index 67a150108..000000000
--- a/cloud_functions/firebase.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "functions": {
- "predeploy": [
- "npm --prefix \"$RESOURCE_DIR\" run lint",
- "npm --prefix \"$RESOURCE_DIR\" run build"
- ]
- }
-}
diff --git a/cloud_functions/functions/.prettierignore b/cloud_functions/functions/.prettierignore
deleted file mode 100644
index c3af85790..000000000
--- a/cloud_functions/functions/.prettierignore
+++ /dev/null
@@ -1 +0,0 @@
-lib/
diff --git a/cloud_functions/functions/package.json b/cloud_functions/functions/package.json
deleted file mode 100644
index db80a6661..000000000
--- a/cloud_functions/functions/package.json
+++ /dev/null
@@ -1,56 +0,0 @@
-{
- "name": "functions",
- "scripts": {
- "updateStatus": "ts-node updateDeployStatus.ts",
- "generateConfig": "ts-node src/generateConfig.ts",
- "lint": "tslint --project tsconfig.json",
- "build": "tsc",
- "serve": "npm run build && firebase serve --only functions",
- "shell": "npm run build && firebase functions:shell",
- "start": "npm run shell",
- "deployFT": "echo 'n\n' | firebase deploy --interactive",
- "logs": "firebase functions:log"
- },
- "engines": {
- "node": "14"
- },
- "main": "lib/index.js",
- "dependencies": {
- "@google-cloud/cloudbuild": "^2.0.6",
- "@google-cloud/firestore": "^4.9.7",
- "@google-cloud/pubsub": "^2.5.0",
- "@google-cloud/storage": "^5.1.2",
- "@sendgrid/mail": "^7.4.2",
- "@slack/web-api": "^6.0.0",
- "algoliasearch": "^4.8.6",
- "firebase-admin": "^9.4.2",
- "firebase-functions": "^3.13.1",
- "imagemin": "^7.0.1",
- "imagemin-mozjpeg": "^9.0.0",
- "imagemin-pngquant": "^9.0.2",
- "lodash": "^4.17.21",
- "sharp": "^0.25.4"
- },
- "devDependencies": {
- "@types/algoliasearch": "^3.34.10",
- "@types/imagemin": "^7.0.0",
- "@types/imagemin-mozjpeg": "^8.0.0",
- "@types/imagemin-pngquant": "^7.0.0",
- "@types/json2csv": "^5.0.1",
- "@types/lodash": "^4.14.158",
- "@types/sharp": "^0.25.1",
- "firebase-tools": "^9.2.2",
- "husky": "^4.2.5",
- "prettier": "^2.1.1",
- "pretty-quick": "^3.0.0",
- "ts-node": "^8.6.2",
- "tslint": "^6.1.0",
- "typescript": "^3.2.2"
- },
- "husky": {
- "hooks": {
- "pre-commit": "pretty-quick --staged"
- }
- },
- "private": true
-}
diff --git a/cloud_functions/functions/src/actionScript/index.ts b/cloud_functions/functions/src/actionScript/index.ts
deleted file mode 100644
index 9529404d6..000000000
--- a/cloud_functions/functions/src/actionScript/index.ts
+++ /dev/null
@@ -1,132 +0,0 @@
-import * as functions from "firebase-functions";
-import * as _ from "lodash";
-import { db, auth } from "../config";
-import * as admin from "firebase-admin";
-import utilFns from "../utils";
-type ActionData = {
- ref: {
- id: string;
- path: string;
- parentId: string;
- tablePath: string;
- };
- schemaDocPath?: string;
- column: any;
- action: "run" | "redo" | "undo";
- actionParams: any;
-};
-// import {
-// makeId,
-// hasGoogleMailServer,
-// hasMissingFields,
-// } from "../utils";
-
-import { hasAnyRole } from "../utils/auth";
-
-const missingFieldsReducer = (data: any) => (acc: string[], curr: string) => {
- if (data[curr] === undefined) {
- return [...acc, curr];
- } else return acc;
-};
-
-const generateSchemaDocPath = (tablePath) => {
- const pathComponents = tablePath.split("/");
- return `_FIRETABLE_/settings/${
- pathComponents[1] === "table" ? "schema" : "groupSchema"
- }/${pathComponents[2]}`;
-};
-const serverTimestamp = admin.firestore.FieldValue.serverTimestamp;
-
-export const actionScript = functions.https.onCall(
- async (data: ActionData, context: functions.https.CallableContext) => {
- try {
- if (!context) {
- throw Error(`You are unauthenticated`);
- }
-
- const { ref, actionParams, column, action, schemaDocPath } = data;
- const _schemaDocPath =
- schemaDocPath ?? generateSchemaDocPath(ref.tablePath);
- const [schemaDoc, rowQuery] = await Promise.all([
- db.doc(_schemaDocPath).get(),
- db.doc(ref.path).get(),
- ]);
- const row = rowQuery.data();
- const schemaDocData = schemaDoc.data();
- if (!schemaDocData) {
- return {
- success: false,
- message: "no schema found",
- };
- }
- const config = schemaDocData.columns[column.key].config;
- const { script, requiredRoles, requiredFields, undo, redo } = config;
- if (!requiredRoles || requiredRoles.length === 0) {
- throw Error(`You need to specify at least one role to run this script`);
- }
- if (!hasAnyRole(requiredRoles, context)) {
- throw Error(`You don't have the required roles permissions`);
- }
-
- const missingRequiredFields = requiredFields
- ? requiredFields.reduce(missingFieldsReducer(row), [])
- : [];
- if (missingRequiredFields.length > 0) {
- throw new Error(
- `Missing required fields:${missingRequiredFields.join(", ")}`
- );
- }
- //
- // get auth
- console.log(
- JSON.stringify({
- undo,
- redo,
- row,
- ref,
- actionParams,
- column,
- schemaDocData,
- script,
- requiredRoles,
- requiredFields,
- })
- );
-
- const result: {
- message: string;
- status: string;
- success: boolean;
- } = await eval(
- `async({row,db, ref,auth,utilFns,actionParams,context})=>{${
- action === "undo" ? config["undo.script"] : script
- }}`
- )({ row, db, auth, utilFns, ref, actionParams, context });
- if (result.success)
- return {
- success: result.success,
- message: result.message,
- cellValue: {
- redo: config["redo.enabled"],
- status: result.status,
- completedAt: serverTimestamp(),
- meta: { ranBy: context.auth!.token.email },
- undo: action !== "undo" && config["undo.enabled"],
- },
- undo: config["undo.enabled"],
- redo: config["redo.enabled"],
- };
- else
- return {
- success: false,
- message: result.message,
- };
- } catch (error) {
- return {
- success: false,
- error,
- message: error.message,
- };
- }
- }
-);
diff --git a/cloud_functions/functions/src/aggregates/index.ts b/cloud_functions/functions/src/aggregates/index.ts
deleted file mode 100644
index 5d15db274..000000000
--- a/cloud_functions/functions/src/aggregates/index.ts
+++ /dev/null
@@ -1,81 +0,0 @@
-import * as functions from "firebase-functions";
-import * as admin from "firebase-admin";
-
-import { db } from "../config";
-import config, { collectionPath, functionName } from "../functionConfig";
-// generated using generateConfig.ts
-
-const incrementor = (v: number) => admin.firestore.FieldValue.increment(v);
-const functionConfig: any = config;
-
-const subDocTrigger = async (
- change: functions.Change,
- context: functions.EventContext
-) => {
- const beforeData = change.before?.data();
- const afterData = change.after?.data();
- const triggerType =
- Boolean(beforeData) && Boolean(afterData)
- ? "update"
- : Boolean(afterData)
- ? "create"
- : "delete";
- const parentDocRef = change.after
- ? change.after.ref.parent.parent
- : change.before.ref.parent.parent;
- const parentDoc = await parentDocRef?.get();
- const parentDocData = parentDoc?.data();
- console.log(
- JSON.stringify({
- parentDocRef,
- parentDocData,
- beforeData,
- afterData,
- triggerType,
- })
- );
- //return false;
- const aggregateData = await functionConfig.reduce(
- async (accAggregate: any, currAggregate) => {
- // check relavent sub-table
- if (currAggregate.subtables.includes(context.params.subCollectionId)) {
- const newValue = await currAggregate.eval(db)({
- beforeData,
- afterData,
- incrementor,
- triggerType,
- });
- if (newValue !== undefined) {
- return {
- ...(await accAggregate),
- ...Object.keys(newValue).reduce((acc, curr) => {
- return {
- ...acc,
- [`${currAggregate.fieldName}.${curr}`]: newValue[curr],
- };
- }, {}),
- };
- } else return await accAggregate;
- } else return await accAggregate;
- },
- {}
- );
- const update = Object.keys(aggregateData).reduce((acc: any, curr: string) => {
- if (aggregateData[curr] !== undefined) {
- return { ...acc, [curr]: aggregateData[curr] };
- } else {
- return acc;
- }
- }, {});
- console.log({ update, aggregateData });
- if (parentDocRef && Object.keys(update).length !== 0) {
- return parentDocRef.update(update);
- }
- return false;
-};
-
-export const FT_aggregates = {
- [functionName]: functions.firestore
- .document(`${collectionPath}/{parentId}/{subCollectionId}/{docId}`)
- .onWrite(subDocTrigger),
-};
diff --git a/cloud_functions/functions/src/algolia/index.ts b/cloud_functions/functions/src/algolia/index.ts
deleted file mode 100644
index 2b54f2055..000000000
--- a/cloud_functions/functions/src/algolia/index.ts
+++ /dev/null
@@ -1,218 +0,0 @@
-import algoliasearch from "algoliasearch";
-import * as functions from "firebase-functions";
-import * as _ from "lodash";
-import { env } from "../config";
-import fnConfig from "../functionConfig"; // generated using generateConfig.ts
-const functionConfig: any = fnConfig;
-
-const APP_ID = env.algolia ? env.algolia.app : "NEEDS_CONFIG";
-const ADMIN_KEY = env.algolia ? env.algolia.key : "NEEDS_CONFIG";
-
-const client = algoliasearch(APP_ID, ADMIN_KEY);
-
-const missingFieldsReducer = (data: any) => (acc: string[], curr: string) => {
- if (data[curr] === undefined) {
- return [...acc, curr];
- } else return acc;
-};
-
-const filterSnapshot = (
- field: { docPath: string; snapshot: any },
- preservedKeys: string[]
-) => {
- return {
- docPath: field.docPath,
- ...preservedKeys.reduce((acc: any, currentKey: string) => {
- const value = _.get(field.snapshot, currentKey);
- if (value) {
- return { ...acc, snapshot: { [currentKey]: value, ...acc.snapshot } };
- } else return acc;
- }, {}),
- };
-};
-
-// returns object of fieldsToSync
-const algoliaReducer = (docData: FirebaseFirestore.DocumentData) => (
- acc: any,
- curr: string | { fieldName: string; snapshotFields: string[] }
-) => {
- if (typeof curr === "string") {
- if (docData[curr] && typeof docData[curr].toDate === "function") {
- return {
- ...acc,
- [curr]: docData[curr].toDate().getTime() / 1000,
- };
- } else if (docData[curr] !== undefined || docData[curr] !== null) {
- return { ...acc, [curr]: docData[curr] };
- } else {
- return acc;
- }
- } else {
- if (docData[curr.fieldName] && curr.snapshotFields) {
- return {
- ...acc,
- [curr.fieldName]: docData[curr.fieldName].map((snapshot) =>
- filterSnapshot(snapshot, curr.snapshotFields)
- ),
- };
- } else {
- return acc;
- }
- }
-};
-
-const addToAlgolia = (
- config: any,
- fieldsToSync: string[],
- requiredFields: string[],
- indexName?: string
-) => (
- snapshot: FirebaseFirestore.DocumentSnapshot,
- context: functions.EventContext
-) => {
- if (config.subTable && config.subTable !== context.params.subCollectionId)
- return false;
- const _index = indexName
- ? indexName
- : `${config.name}${config.subTable ? `_${config.subTable}` : ""}`;
- const objectID = snapshot.id;
- const docData = snapshot.data();
- if (!docData) return false; // returns if theres no data in the doc
- const missingRequiredFields = requiredFields.reduce(
- missingFieldsReducer(docData),
- []
- );
- if (missingRequiredFields.length > 0) {
- throw new Error(
- `Missing required fields:${missingRequiredFields.join(", ")}`
- );
- }
- const algoliaData = fieldsToSync.reduce(algoliaReducer(docData), {});
- if (Object.keys(algoliaData).length === 0) return false; // returns if theres nothing to sync
- const index = client.initIndex(_index); // initialize algolia index
- return index.saveObject({ ...algoliaData, objectID }); // add new algolia entry
-};
-
-const updateAlgolia = (
- config: any,
- fieldsToSync: string[],
- requiredFields: string[],
- indexName?: string
-) => async (
- snapshot: functions.Change,
- context: functions.EventContext
-) => {
- const objectID = snapshot.after.id;
- try {
- if (config.subTable && config.subTable !== context.params.subCollectionId)
- return false;
- const _index = indexName
- ? indexName
- : `${config.name}${config.subTable ? `_${config.subTable}` : ""}`;
-
- const docData = snapshot.after.data();
- if (!docData) return false; // returns if theres no data in the doc
-
- const missingRequiredFields = requiredFields.reduce(
- missingFieldsReducer(docData),
- []
- );
- if (missingRequiredFields.length > 0) {
- throw new Error(
- `Missing required fields:${missingRequiredFields.join(", ")}`
- );
- }
- const algoliaData = fieldsToSync.reduce(algoliaReducer(docData), {});
- if (Object.keys(algoliaData).length === 0) return false; // returns if theres nothing to sync
- const index = client.initIndex(_index); // initialize algolia index
- const algoliaTask = await index.saveObject({ ...algoliaData, objectID }); // add update algolia entry
-
- return algoliaTask;
- } catch (error) {
- console.error(JSON.stringify({ error, objectID }));
- return false;
- }
-};
-
-const deleteFromAlgolia = (config: any, indexName?: string) => (
- snapshot: FirebaseFirestore.DocumentSnapshot,
- context: functions.EventContext
-) => {
- if (config.subTable && config.subTable !== context.params.subCollectionId)
- return false;
- const _index = indexName
- ? indexName
- : `${config.name}${config.subTable ? `_${config.subTable}` : ""}`;
- const objectID = snapshot.id;
- const index = client.initIndex(_index); // initialize algolia index
- return index.deleteObject(objectID); // delete algolia entry
-};
-
-const documentPathGenerator = (config) =>
- `${
- config.subTable
- ? `${config.name}/{parentId}/{subCollectionId}/{docId}`
- : `${config.name}/{docId}`
- }`;
-/**
- * returns 3 different trigger functions (onCreate,onUpdate,onDelete) in an object
- * @param config configuration object
- */
-const algoliaFnsGenerator = (config) => ({
- onCreate: functions.firestore
- .document(documentPathGenerator(config))
- .onCreate(
- config.indices
- ? (snapshot, context) =>
- Promise.all(
- config.indices.map((index) =>
- addToAlgolia(
- config,
- index.fieldsToSync,
- config.requiredFields ?? [],
- index.name
- )(snapshot, context)
- )
- )
- : addToAlgolia(config, config.fieldsToSync, config.requiredFields ?? [])
- ),
- onUpdate: functions.firestore
- .document(documentPathGenerator(config))
- .onUpdate(
- config.indices
- ? (snapshot, context) =>
- Promise.all(
- config.indices.map((index) =>
- updateAlgolia(
- config,
- index.fieldsToSync,
- config.requiredFields ?? [],
- index.name
- )(snapshot, context)
- )
- )
- : updateAlgolia(
- config,
- config.fieldsToSync,
- config.requiredFields ?? []
- )
- ),
- onDelete: functions.firestore
- .document(documentPathGenerator(config))
- .onDelete(
- config.indices
- ? (snapshot, context) =>
- Promise.all(
- config.indices.map((index) =>
- deleteFromAlgolia(config, index.name)(snapshot, context)
- )
- )
- : deleteFromAlgolia(config)
- ),
-});
-
-export const FT_algolia = {
- [`${functionConfig.name}${
- functionConfig.subTable ? `${functionConfig.subTable}` : ""
- }`]: { ...algoliaFnsGenerator(functionConfig) },
-};
diff --git a/cloud_functions/functions/src/algoliaSearchKey.ts b/cloud_functions/functions/src/algoliaSearchKey.ts
deleted file mode 100644
index a518774c2..000000000
--- a/cloud_functions/functions/src/algoliaSearchKey.ts
+++ /dev/null
@@ -1,51 +0,0 @@
-import algoliasearch from "algoliasearch";
-import * as functions from "firebase-functions";
-import { env } from "./config";
-
-const algoliaClient = algoliasearch(env.algolia.app, env.algolia.key);
-
-export const getAlgoliaSearchKey = functions.https.onCall(async (
- data: { index: string },
- context: functions.https.CallableContext
-) => {
- const requestedIndex = data.index
- try {
- if (!context.auth || !context.auth.token) throw new Error("Unauthenticated")
-
- const allIndicesRoles = ['ADMIN',"TEAM"] // you can add more roles here that need access to all algolia indices
-
- const rolesIndicesAccess = {
- "ROLE":["index_1","index_2"]
- }
- const userRoles = context.auth.token.roles
- if (userRoles.some(role=> allIndicesRoles.includes(role)||rolesIndicesAccess[role].includes(requestedIndex))){
- const validUntil = Math.floor(Date.now() / 1000) + 3600;
- const key = algoliaClient.generateSecuredApiKey(
- env.algolia.search,
- {
- filters:"",
- validUntil,
- restrictIndices: [requestedIndex],
- userToken: context.auth.uid,
- }
- );
- return {
- data: key,
- success: true,
- };
- }else{
- return {
- message: 'Missing Required roles for this index',
- success: false,
- };
- }
-
- } catch (error) {
- return {
- success: false,
- error,
- message: error.message,
- };
- }
-})
-
diff --git a/cloud_functions/functions/src/backup.ts b/cloud_functions/functions/src/backup.ts
deleted file mode 100644
index 2a5e0b4eb..000000000
--- a/cloud_functions/functions/src/backup.ts
+++ /dev/null
@@ -1,101 +0,0 @@
-import * as functions from "firebase-functions";
-import * as firestore from "@google-cloud/firestore";
-import { hasAnyRole } from "./utils/auth";
-
-const client = new firestore.v1.FirestoreAdminClient();
-
-// Replace BUCKET_NAME
-const bucket = "gs://BUCKET_NAME";
-/*
-const restoreFirestoreBackup = (collectionIds: string[] = []) => {
- const projectId = process.env.GCP_PROJECT || process.env.GCLOUD_PROJECT;
- const databaseName = client.databasePath(projectId, "(default)");
- const date = new Date();
-
- const backupFolder = `${date.getFullYear()}-${
- date.getMonth() + 1
- }-${date.getDate()}`;
- const inputUriPrefix = bucket + "/" + backupFolder;
- console.log(inputUriPrefix);
- return client
- .importDocuments({
- name: databaseName,
- inputUriPrefix,
- // Leave collectionIds empty to export all collections
- // or set to a list of collection IDs to export,
- // collectionIds: ['users', 'posts']
- collectionIds,
- })
- .then((responses) => {
- const response = responses[0];
- console.log(`Operation Name: ${response["name"]}`);
- return response;
- })
- .catch((err) => {
- console.error(err);
- throw new Error("import operation failed");
- });
-};
-
-export const scheduledFirestoreImport = functions.pubsub
- .schedule("every 24 hours")
- .onRun((context) => {
- console.log(context);
- return restoreFirestoreBackup();
- });
- */
-
-const firestoreBackup = (collectionIds: string[] = []) => {
- const projectId = process.env.GCP_PROJECT || process.env.GCLOUD_PROJECT;
- const databaseName = client.databasePath(projectId ?? "", "(default)");
- const date = new Date();
-
- const backupFolder = `${date.getUTCFullYear()}-${
- date.getUTCMonth() + 1
- }-${date.getUTCDate()}-${date.getUTCHours()}`;
-
- return client
- .exportDocuments({
- name: databaseName,
- outputUriPrefix: bucket + "/" + backupFolder,
- // Leave collectionIds empty to export all collections
- // or set to a list of collection IDs to export,
- // collectionIds: ['users', 'posts']
- collectionIds,
- })
- .then((responses) => {
- const response = responses[0];
- console.log(`Operation Name: ${response["name"]}`);
- return response;
- })
- .catch((err) => {
- console.error(err);
- throw new Error("Export operation failed");
- });
-};
-export const scheduledFirestoreBackup = functions.pubsub
- .schedule("every 12 hours")
- .onRun((context) => {
- console.log(context);
- return firestoreBackup();
- });
-
-export const callableFirestoreBackup = functions.https.onCall(
- async (data, context) => {
- console.log(data);
- const authorized = hasAnyRole(["ADMIN"], context);
- if (!context.auth || !authorized) {
- console.warn(`unauthorized user${context}`);
- return {
- success: false,
- message: "you don't have permissions to send this email",
- };
- } else {
- await firestoreBackup();
- return {
- success: true,
- message: "backup ran",
- };
- }
- }
-);
diff --git a/cloud_functions/functions/src/buildTriggers/index.ts b/cloud_functions/functions/src/buildTriggers/index.ts
deleted file mode 100644
index 5e549acf2..000000000
--- a/cloud_functions/functions/src/buildTriggers/index.ts
+++ /dev/null
@@ -1,96 +0,0 @@
-import * as functions from "firebase-functions";
-import { hasAnyRole } from "../utils/auth";
-import { serverTimestamp } from "../utils";
-import { db } from "../config";
-const { CloudBuildClient } = require("@google-cloud/cloudbuild");
-const cb = new CloudBuildClient();
-
-export const triggerCloudBuild = functions.https.onCall(
- async (
- data: {
- ref: {
- id: string;
- path: string;
- parentId: string;
- };
- action: "run" | "redo" | "undo";
- },
- context: functions.https.CallableContext
- ) => {
- const {
- ref, // action
- } = data;
-
- const authorized = hasAnyRole(["ADMIN"], context);
- if (!context.auth || !authorized) {
- console.warn(`unauthorized user${context}`);
- return {
- success: false,
- message: "you don't have permission to trigger a build",
- };
- }
- const doc = await db.doc(ref.path).get();
- const row = doc.data();
- if (!row) throw Error("No row data");
- const { triggerId, branch, projectId, groupName, functionConfig } = row;
- // Starts a build against the branch provided.
- const [resp] = await cb.runBuildTrigger({
- projectId, //project hosting cloud build
- triggerId,
- source: {
- branchName: branch,
- substitutions: {
- _PROJECT_ID: projectId,
- _FUNCTIONS_GROUP: groupName,
- _FUNCTION_CONFIG: functionConfig,
- _REQUEST_DOC_PATH: ref.path,
- },
- },
- });
- const buildId = resp.metadata.build.id;
- const logUrl = resp.metadata.build.logUrl;
- console.log({ buildId, logUrl });
- await db
- .doc(ref.path)
- .update({ buildId, logUrl, buildDuration: { start: serverTimestamp() } });
- if (buildId && logUrl) {
- return {
- message: "cloud functions are snow flakes",
- cellValue: {
- redo: true,
- status: `Triggered`,
- completedAt: serverTimestamp(),
- meta: { ranBy: context.auth.token.email },
- undo: false,
- },
- success: true,
- };
- }
- return false;
- }
-);
-
-export const cloudBuildUpdates = functions.pubsub
- .topic("cloud-builds")
- .onPublish(async (message, context) => {
- console.log(JSON.stringify(message));
- const { buildId, status } = message.attributes;
- console.log(JSON.stringify({ buildId, status }));
- //message
- //status: "SUCCESS"
- //buildId: "1a6d7819-aa35-486c-a29c-fb67eb39430f"
-
- const query = await db
- .collection("cloudFunctions")
- .where("buildId", "==", buildId)
- .get();
-
- if (query.docs.length !== 0) {
- const update = { status };
- if (status === "SUCCESS" || status === "FAILURE") {
- update["buildDuration.end"] = serverTimestamp();
- }
- await query.docs[0].ref.update(update);
- }
- return true;
- });
diff --git a/cloud_functions/functions/src/callable.ts b/cloud_functions/functions/src/callable.ts
deleted file mode 100644
index ef4d373a4..000000000
--- a/cloud_functions/functions/src/callable.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import * as functions from "firebase-functions";
-import * as _ from "lodash";
-import { hasAnyRole } from "./utils/auth";
-import { auth } from "./config";
-
-// Impersonator Auth callable takes email and returns JWT of user on firebaseAuth
-// requires a user admin role
-
-export const ImpersonatorAuth = functions.https.onCall(
- async (data, context) => {
- try {
- if (hasAnyRole(["ADMIN"], context)) {
- const user = await auth.getUserByEmail(data.email);
- const jwt = await auth.createCustomToken(user.uid);
- return {
- success: true,
- jwt,
- message: "successfully generated token",
- };
- } else {
- return {
- success: false,
- message: "admin role is required",
- };
- }
- } catch (error) {
- return {
- success: false,
- message: JSON.stringify(error),
- };
- }
- }
-);
diff --git a/cloud_functions/functions/src/collectionSync/index.ts b/cloud_functions/functions/src/collectionSync/index.ts
deleted file mode 100644
index 8ca25e420..000000000
--- a/cloud_functions/functions/src/collectionSync/index.ts
+++ /dev/null
@@ -1,158 +0,0 @@
-import * as functions from "firebase-functions";
-
-import { db } from "../config";
-
-import * as _ from "lodash";
-import { replacer } from "../utils";
-import config from "../functionConfig"; // generated using generateConfig.ts
-const functionConfig: any = config;
-// returns object of fieldsToSync
-const docReducer = (docData: FirebaseFirestore.DocumentData) => (
- acc: any,
- curr: string
-) => {
- if (docData[curr] !== undefined && docData[curr] !== null)
- return { ...acc, [curr]: docData[curr] };
- else return acc;
-};
-
-/**
- *
- * @param targetCollection
- * @param fieldsToSync
- */
-const cloneDoc = (targetCollection: string, fieldsToSync: string[]) => (
- snapshot: FirebaseFirestore.DocumentSnapshot
-) => {
- const docId = snapshot.id;
- const docData = snapshot.data();
- if (!docData) return false; // returns if theres no data in the doc
- const syncData = fieldsToSync.reduce(docReducer(docData), {});
- if (Object.keys(syncData).length === 0) return false; // returns if theres nothing to sync
- console.log(`creating new doc or forcing update ${docId}`);
- const collectionPath = targetCollection.replace(
- /\{\{(.*?)\}\}/g,
- replacer(docData)
- );
- if (collectionPath.includes("//")) {
- console.log(`${collectionPath} is an invalid collection path`);
- return false;
- }
- db.collection(collectionPath)
- .doc(docId)
- .set({ ...syncData, syncedAt: new Date() }, { merge: true })
- .catch((error) => console.error(error));
- return true;
-};
-
-/**
- *
- * @param targetCollection
- * @param fieldsToSync
- */
-const syncDoc = (targetCollection: string, fieldsToSync: string[]) => async (
- snapshot: FirebaseFirestore.DocumentSnapshot
-) => {
- const docId = snapshot.id;
- const docData = snapshot.data();
- if (!docData) return false; // returns if theres no data in the doc
- const syncData = fieldsToSync.reduce(docReducer(docData), {});
-
- const collectionPath = targetCollection.replace(
- /\{\{(.*?)\}\}/g,
- replacer(docData)
- );
-
- if (collectionPath.includes("//")) {
- console.log(`${collectionPath} is an invalid collection path`);
- return false;
- }
- if (Object.keys(syncData).length === 0) return false; // returns if theres nothing to sync
- const targetDoc = await db.collection(collectionPath).doc(docId).get();
- if (!targetDoc.exists) return false;
- db.collection(collectionPath)
- .doc(docId)
- .update({ ...syncData, syncedAt: new Date() })
- .catch((error) => console.error(error));
- return true;
-};
-
-const deleteDoc = (targetCollection: string) => async (
- snapshot: FirebaseFirestore.DocumentSnapshot,
- context: functions.EventContext
-) => {
- const { docId } = context.params;
- return db.collection(targetCollection).doc(docId).delete();
-};
-
-/**
- * onUpdate change to snapshot adapter
- * @param targetCollection
- * @param fieldsToSync
- */
-const syncDocOnUpdate = (
- targetCollection: string,
- fieldsToSync: string[],
- forcedUpdate: boolean
-) => (snapshot: functions.Change) => {
- const afterData = snapshot.after.data();
- const beforeData = snapshot.before.data();
- const hasChanged = !_.isEqual(afterData, beforeData);
- if (hasChanged) {
- if (forcedUpdate === true) {
- return cloneDoc(targetCollection, fieldsToSync)(snapshot.after);
- } else {
- return syncDoc(targetCollection, fieldsToSync)(snapshot.after);
- }
- } else {
- console.warn("no change detected");
- return false;
- }
-};
-
-/**
- * returns 2 different trigger functions (onCreate,onUpdate) in an object
- * @param collectionConfig configuration object
- * onCreate
- * onUpdate
- * onDelete
- * source
- * target
- * fieldsToSync
- *
- */
-const collectionSyncFnsGenerator = (collectionConfig) =>
- Object.entries({
- onCreate: collectionConfig.onCreate
- ? functions.firestore
- .document(`${collectionConfig.source}/{docId}`)
- .onCreate(
- cloneDoc(collectionConfig.target, collectionConfig.fieldsToSync)
- )
- : null,
- onUpdate: collectionConfig.onUpdate
- ? functions.firestore
- .document(`${collectionConfig.source}/{docId}`)
- .onUpdate(
- syncDocOnUpdate(
- collectionConfig.target,
- collectionConfig.fieldsToSync,
- collectionConfig.forcedUpdate
- )
- )
- : null,
- onDelete: collectionConfig.onDelete
- ? functions.firestore
- .document(`${collectionConfig.source}/{docId}`)
- .onDelete(deleteDoc(collectionConfig.target))
- : null,
- }).reduce((a, [k, v]) => (v === null ? a : { ...a, [k]: v }), {});
-
-//export default collectionSyncFnsGenerator;
-export const FT_sync = {
- [`${`${`${functionConfig.source}`
- .replace(/\//g, "_")
- .replace(/_{.*?}_/g, "_")}`}2${`${`${functionConfig.target}`
- .replace(/\//g, "_")
- .replace(/_{.*?}_/g, "_")}`}`]: collectionSyncFnsGenerator(functionConfig),
-};
diff --git a/cloud_functions/functions/src/compressedThumbnail/index.ts b/cloud_functions/functions/src/compressedThumbnail/index.ts
deleted file mode 100644
index abc28294a..000000000
--- a/cloud_functions/functions/src/compressedThumbnail/index.ts
+++ /dev/null
@@ -1,113 +0,0 @@
-import * as functions from "firebase-functions";
-// tslint:disable-next-line: no-import-side-effect
-import "../config";
-import * as admin from "firebase-admin";
-import * as path from "path";
-import * as os from "os";
-import * as fs from "fs";
-import * as sharp from "sharp";
-import * as imagemin from "imagemin";
-import * as imageminMozjpeg from "imagemin-mozjpeg";
-import imageminPngquant from "imagemin-pngquant";
-import config_ from "../functionConfig";
-const SUPPORTED_TYPES = ["image/jpeg", "image/png"];
-const DEFAULT_SIZES = ["400x400", "200x200", "100x100"];
-const config: any = config_;
-const sizes =
- config && Array.isArray(config.sizes) && typeof config.sizes[0] === "string"
- ? config.sizes
- : DEFAULT_SIZES;
-const excludePaths =
- config &&
- Array.isArray(config.excludes) &&
- typeof config.excludes[0] === "string"
- ? config.excludes
- : [];
-export const FT_compressedThumbnail = functions.storage
- .object()
- .onFinalize(async (object) => {
- // Log file name, size, and content type for monitoring
- console.log(object.name, object.size, object.contentType);
- // Exit if this is triggered on a file that is not an image.
- if (!object.contentType || !SUPPORTED_TYPES.includes(object.contentType)) {
- console.log("Unsupported type", object.contentType);
- return null;
- }
- // Exit if this is already a compressed thumbnail.
- if (object.metadata?.resizedImage) {
- console.log("This is already a compressed thumbnail", object.name);
- return null;
- }
- // Get Firebase Storage download token
- const token = object.metadata?.firebaseStorageDownloadTokens;
-
- const filePath: string = object.name!;
-
- // Check if file should be excluded based off path
- for (const excludePath of excludePaths)
- if (filePath.startsWith(excludePath)) {
- console.log("File excluded from path", excludePath);
- return null;
- }
- const baseFileName = path.basename(filePath, path.extname(filePath));
- const tempLocalFile = path.join(
- os.tmpdir(),
- baseFileName + path.extname(filePath)
- );
- // Download file from bucket.
- const bucket = admin.storage().bucket(object.bucket);
- await bucket.file(filePath).download({ destination: tempLocalFile });
- for (const size of sizes) {
- try {
- const thumbFilePath = path.normalize(
- path.format({
- dir: path.dirname(filePath),
- name: baseFileName + "__" + size,
- ext: path.extname(filePath),
- })
- );
- const tempLocalThumbFile = path.join(
- os.tmpdir(),
- path.basename(thumbFilePath)
- );
- // Resize image to thumbnail size
- const resized = await sharp(tempLocalFile)
- .rotate()
- .resize(
- parseInt(size.split("x")[0], 10),
- parseInt(size.split("x")[1], 10),
- {
- fit: "inside",
- withoutEnlargement: true,
- }
- )
- .toBuffer();
- // Compress the image
- const compressed = await imagemin.buffer(resized, {
- plugins: [
- imageminMozjpeg({ quality: 75 }),
- imageminPngquant({ quality: [0.6, 0.8] }),
- ],
- });
- fs.writeFileSync(tempLocalThumbFile, compressed);
- // Upload the image
- await bucket.upload(tempLocalThumbFile, {
- destination: thumbFilePath,
- contentType: object.contentType,
- metadata: {
- metadata: {
- firebaseStorageDownloadTokens: token,
- resizedImage: true,
- },
- },
- });
- console.log(size, "thumbnail uploaded to Storage at", thumbFilePath);
- // Once the image has been converted delete the local files to free up disk space.
- fs.unlinkSync(tempLocalThumbFile);
- } catch (e) {
- console.error(`Failed to generate thumbnail size: ${size}`, e);
- }
- }
- fs.unlinkSync(tempLocalFile);
- return filePath;
- });
diff --git a/cloud_functions/functions/src/config.ts b/cloud_functions/functions/src/config.ts
deleted file mode 100644
index 0919f1bbc..000000000
--- a/cloud_functions/functions/src/config.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-// Initialize Firebase Admin
-import * as functions from "firebase-functions";
-import * as admin from "firebase-admin";
-admin.initializeApp();
-
-// Initialize Cloud Firestore Database
-export const db = admin.firestore();
-// Initialize Auth
-export const auth = admin.auth();
-
-const settings = { timestampsInSnapshots: true };
-db.settings(settings);
-export const env = functions.config();
diff --git a/cloud_functions/functions/src/constants/Collections.ts b/cloud_functions/functions/src/constants/Collections.ts
deleted file mode 100644
index c02942707..000000000
--- a/cloud_functions/functions/src/constants/Collections.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-enum Collections {
- fireMail = "firemail",
- emailOTP = "emailOTP",
-}
diff --git a/cloud_functions/functions/src/derivatives/index.ts b/cloud_functions/functions/src/derivatives/index.ts
deleted file mode 100644
index 31db8a62a..000000000
--- a/cloud_functions/functions/src/derivatives/index.ts
+++ /dev/null
@@ -1,78 +0,0 @@
-import * as functions from "firebase-functions";
-
-import { db } from "../config";
-import config, { collectionPath, functionName } from "../functionConfig";
-// generated using generateConfig.ts
-const functionConfig: any = config;
-
-const shouldEvaluateReducer = (listeners, before, after) =>
- listeners.reduce((acc: Boolean, currField: string) => {
- if (acc) return true;
- else
- return (
- JSON.stringify(before[currField]) !== JSON.stringify(after[currField])
- );
- }, false);
-
-export const derivativeOnChange = async (
- ref: FirebaseFirestore.DocumentReference,
- beforeData: FirebaseFirestore.DocumentData,
- afterData: FirebaseFirestore.DocumentData
-) => {
- const update = await functionConfig.reduce(
- async (accUpdates: any, currDerivative) => {
- const shouldEval = shouldEvaluateReducer(
- currDerivative.listenerFields,
- beforeData,
- afterData
- );
- if (shouldEval) {
- const newValue = await currDerivative.eval(db)({
- row: afterData,
- ref,
- });
- if (newValue !== undefined) {
- return {
- ...(await accUpdates),
- [currDerivative.fieldName]: newValue,
- };
- }
- }
- return await accUpdates;
- },
- {}
- );
- if (Object.keys(update).length !== 0) {
- return ref.update(update);
- }
- return false;
-};
-
-export const derivativeOnCreate = async (
- snapshot: functions.firestore.DocumentSnapshot
-) => {
- const docData = snapshot.data();
-
- if (!docData) return false;
- return derivativeOnChange(snapshot.ref, {}, docData);
-};
-
-export const derivativeOnUpdate = async (
- Change: functions.Change
-) => {
- const beforeData = Change.before.data();
- const afterData = Change.after.data();
- if (!beforeData || !afterData) return false;
- return derivativeOnChange(Change.after.ref, beforeData, afterData);
-};
-
-export const FT_derivatives = {
- [functionName]: {
- u: functions.firestore
- .document(`${collectionPath}/{docId}`)
- .onUpdate(derivativeOnUpdate),
- c: functions.firestore
- .document(`${collectionPath}/{docId}`)
- .onCreate(derivativeOnCreate),
- },
-};
diff --git a/cloud_functions/functions/src/emailOnTrigger/index.ts b/cloud_functions/functions/src/emailOnTrigger/index.ts
deleted file mode 100644
index 7d5e84659..000000000
--- a/cloud_functions/functions/src/emailOnTrigger/index.ts
+++ /dev/null
@@ -1,144 +0,0 @@
-import { firestore } from "firebase-functions";
-
-import { sendEmail } from "../utils/email";
-import { hasRequiredFields } from "../utils";
-import { db } from "../config";
-import _config from "../functionConfig"; // generated using generateConfig.ts
-const functionConfig: any = _config;
-type EmailOnTriggerConfig = {
- collectionPath: string;
- templateId: string;
- categories: string[];
- onCreate: Boolean;
- from: Function;
- to: Function;
- attachments?: Function;
- bcc?: Function;
- cc?: Function;
- requiredFields: string[];
- shouldSend: (
- snapshot:
- | firestore.DocumentSnapshot
- | {
- before: firestore.DocumentSnapshot;
- after: firestore.DocumentSnapshot;
- }
- ) => Boolean;
- onUpdate: Boolean;
-};
-const emailOnCreate = (config: EmailOnTriggerConfig) =>
- firestore
- .document(`${config.collectionPath}/{docId}`)
- .onCreate(async (snapshot) => {
- try {
- const snapshotData = snapshot.data();
- if (!snapshotData) throw Error("no snapshot data");
-
- const shouldSend = config.shouldSend(snapshot);
- const hasAllRequiredFields = hasRequiredFields(
- config.requiredFields,
- snapshotData
- );
- const from = await config.from(snapshotData, db);
- const to = await config.to(snapshotData, db);
-
- const optionalFields = await ["attachments", "cc", "bcc"].reduce(
- async (accOptions, currOption) => {
- if (config[currOption]) {
- return {
- ...(await accOptions),
- [currOption]: await config[currOption](snapshotData, db),
- };
- } else return await accOptions;
- },
- {}
- );
- console.log(JSON.stringify({ optionalFields }));
- if (shouldSend && hasAllRequiredFields) {
- const msg = {
- from,
- personalizations: [
- {
- to,
- cc: optionalFields["cc"],
- bcc: optionalFields["bcc"],
- dynamic_template_data: {
- ...snapshotData,
- },
- },
- ],
- template_id: config.templateId,
- categories: config.categories,
- attachments: optionalFields["attachments"],
- };
- console.log({ msg });
- const resp = await sendEmail(msg);
- console.log({ resp });
- return resp;
- } else {
- console.log("requirements were not met");
- return false;
- }
- } catch (error) {
- console.warn("Failed", JSON.stringify(error));
- return false;
- }
- });
-
-const emailOnUpdate = (config: EmailOnTriggerConfig) =>
- firestore
- .document(`${config.collectionPath}/{docId}`)
- .onUpdate(async (change) => {
- try {
- const beforeData = change.before.data();
- const afterData = change.after.data();
- if (!beforeData || !afterData) throw Error("no data found in snapshot");
- const shouldSend = config.shouldSend(change);
- const hasAllRequiredFields = hasRequiredFields(
- config.requiredFields,
- afterData
- );
- const dynamic_template_data = config.requiredFields.reduce(
- (acc: any, curr: string) => {
- return { ...acc, [curr]: afterData[curr] };
- },
- {}
- );
- if (shouldSend && hasAllRequiredFields) {
- const from = await config.from(afterData, db);
- const to = await config.to(afterData, db);
- const msg = {
- from,
- personalizations: [
- {
- to,
- dynamic_template_data,
- },
- ],
- template_id: config.templateId,
- categories: config.categories,
- };
- await sendEmail(msg);
-
- return true;
- } else {
- console.log("requirements were not met");
- return false;
- }
- } catch (error) {
- console.warn(error);
- return false;
- }
- });
-
-const emailOnTriggerFns = (config: EmailOnTriggerConfig) =>
- Object.entries({
- onCreate: config.onCreate ? emailOnCreate(config) : null,
- onUpdate: config.onUpdate ? emailOnUpdate(config) : null,
- }).reduce((a, [k, v]) => (v === null ? a : { ...a, [k]: v }), {});
-
-export const FT_email = {
- [`${`${functionConfig.collectionPath}`
- .replace(/\//g, "_")
- .replace(/_{.*?}_/g, "_")}`]: emailOnTriggerFns(functionConfig),
-};
diff --git a/cloud_functions/functions/src/functionConfig.ts b/cloud_functions/functions/src/functionConfig.ts
deleted file mode 100644
index f412540ae..000000000
--- a/cloud_functions/functions/src/functionConfig.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export const collectionPath = ''
-export const functionName = ''
-export default {}
\ No newline at end of file
diff --git a/cloud_functions/functions/src/generateConfig.ts b/cloud_functions/functions/src/generateConfig.ts
deleted file mode 100644
index 8690e74a3..000000000
--- a/cloud_functions/functions/src/generateConfig.ts
+++ /dev/null
@@ -1,98 +0,0 @@
-const fs = require("fs");
-// Initialize Firebase Admin
-import * as admin from "firebase-admin";
-// Initialize Firebase Admin
-//const serverTimestamp = admin.firestore.FieldValue.serverTimestamp;
-//const serviceAccount = require('../firebase-credentials.json')
-//admin.initializeApp({credential: admin.credential.cert(serviceAccount)});
-admin.initializeApp();
-const db = admin.firestore();
-const main = async (functionType: string, configString: string) => {
- let configData;
- switch (functionType) {
- case "FT_derivatives":
- const isCollectionGroup = configString.includes("/");
- const isSubtable = configString.includes("/subTables/");
- const collectionPath = `${configString}`;
- const schemaPath =
- isCollectionGroup && !isSubtable
- ? `/_FIRETABLE_/settings/groupSchema/${configString.split("/").pop()}`
- : `_FIRETABLE_/settings/schema/${collectionPath}`;
- const schemaDoc = await db.doc(schemaPath).get();
- const schemaData = schemaDoc.data();
- if (!schemaData) return;
- const derivativeColumns = Object.values(schemaData.columns).filter(
- (col: any) => col.type === "DERIVATIVE"
- );
- const config = derivativeColumns.reduce((acc, currColumn: any) => {
- return `${acc}{
- fieldName:'${currColumn.key}',eval:(db)=> async ({row,ref}) =>{${
- currColumn.config.script
- }},listenerFields:[${(currColumn.config.listenerFields ?? [])
- .map((f) => `"${f}"`)
- .join(",")}]},`;
- }, ``);
-
- configData = `export default [${config}]\nexport const collectionPath ="${
- isSubtable
- ? ((path) => {
- const pathTables = path.split("/subTables/");
- const subcollection = pathTables.pop();
- return `${pathTables
- .map((t) => `${t}/{${t.replace(/-/g, "_")}DocId}`)
- .join("/")}/${subcollection}`;
- })(collectionPath)
- : collectionPath
- }"`;
- break;
-
- case "FT_extension":
- const extensionSchemaDoc = await db
- .doc(`_FIRETABLE_/settings/schema/${configString}`)
- .get();
- const extensionSchemaData = extensionSchemaDoc.data();
-
- configData = `export default [${extensionSchemaData?.extensions.join(
- ",\n"
- )}]\n export const collectionPath='${configString}';`;
- case "FT_aggregates":
- const _schemaDoc = await db
- .doc(`_FIRETABLE_/settings/schema/${configString}`)
- .get();
- const _schemaData = _schemaDoc.data();
- if (!_schemaData) return;
- const aggregateColumns = Object.values(_schemaData.columns).filter(
- (col: any) => col.type === "AGGREGATE"
- );
- const _config = aggregateColumns.reduce((acc, currColumn: any) => {
- return `${acc}{
- fieldName:'${
- currColumn.key
- }',eval:(db)=> async ({aggregateState,incrementor,triggerType,change,afterData,beforeData}) =>{${
- currColumn.config.script
- }},subtables:[${currColumn.config.subtables
- .map((t) => `"${t}"`)
- .join(",")}]},`;
- }, ``);
-
- configData = `export default [${_config}]\nexport const collectionPath ="${configString}"`;
- break;
- case "FT_subTableStats":
- configData = `export const collectionPath ="${configString}"\nexport default []`;
- break;
- default:
- configData = `export default ${configString}\n export const collectionPath=''`;
- break;
- }
- configData =
- configData +
- '\nexport const functionName = collectionPath.replace("-", "_").replace(/\\//g, "_").replace(/_{.*?}_/g, "_")';
- console.log({ configData });
- fs.writeFileSync("./src/functionConfig.ts", configData);
- return;
-};
-
-main(process.argv[2], process.argv[3])
- .catch((err) => console.log(err))
- .then(() => console.log("this will succeed"))
- .catch(() => "obligatory catch");
diff --git a/cloud_functions/functions/src/history/index.ts b/cloud_functions/functions/src/history/index.ts
deleted file mode 100644
index 1fe62a1cc..000000000
--- a/cloud_functions/functions/src/history/index.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import * as functions from "firebase-functions";
-import * as _ from "lodash";
-import { db } from "../config";
-
-import config from "../functionConfig"; // generated using generateConfig.ts
-const functionConfig: any = config;
-
-const historySnapshot = (trackedFields: string[]) => async (
- change: functions.Change
-) => {
- const before = change.before.data();
- const after = change.after.data();
- const docPath = change.after.ref.path;
- if (!before || !after) return false;
- const trackedChanges: any = {};
- trackedFields.forEach((field) => {
- if (!_.isEqual(before[field], after[field]))
- trackedChanges[field] = after[field];
- });
- if (!_.isEmpty(trackedChanges)) {
- await db
- .doc(docPath)
- .collection("historySnapshots")
- .add({ ...before, archivedAt: new Date() });
- return true;
- } else return false;
-};
-
-const historySnapshotFnsGenerator = (collection) =>
- functions.firestore
- .document(`${collection.name}/{docId}`)
- .onUpdate(historySnapshot(collection.trackedFields));
-
-//export default historySnapshotFnsGenerator;
-
-export const FT_history = {
- [functionConfig.name
- .replace(/\//g, "_")
- .replace(/_{.*?}_/g, "_")]: historySnapshotFnsGenerator(functionConfig),
-};
diff --git a/cloud_functions/functions/src/index.ts b/cloud_functions/functions/src/index.ts
deleted file mode 100644
index 8a92f1bd5..000000000
--- a/cloud_functions/functions/src/index.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-// export { triggerCloudBuild, cloudBuildUpdates } from "./buildTriggers"; // a callable used for triggering cloudbuild to build and deploy configurable cloud functions
-// export {
-// scheduledFirestoreBackup, // callableFirestoreBackup
-// } from "./backup";
-// import * as callableFns from "./callable";
-
-// export const callable = callableFns;
-
-// // all the cloud functions bellow are deployed using the triggerCloudBuild callable function
-// // these functions are designed to be built and deployed based on the configuration passed through the callable
-
-// export { FT_aggregates } from "./aggregates";
-// export { FT_subTableStats } from "./subTableStats";
-
-// export { actionScript } from "./actionScript";
-
-// export { webhook } from "./webhooks";
-
-// export { FT_snapshotSync } from "./snapshotSync";
-
-// export { FT_compressedThumbnail } from "./compressedThumbnail";
-
-export { getAlgoliaSearchKey } from "./algoliaSearchKey";
-
-//deprecated, updated implementation moved to FT_build folder and used within extensions table functions
-// export { FT_derivatives } from "./derivatives";
-// export { FT_algolia } from "./algolia";
-// export { FT_email } from "./emailOnTrigger";
-// export { FT_slack } from "./slackOnTrigger";
-// export { FT_sync } from "./collectionSync";
-// export { FT_extension } from "./extensions";
-// export { FT_history } from "./history";
-// export { slackBotMessageOnCreate } from "./slackOnTrigger/trigger";
diff --git a/cloud_functions/functions/src/slackOnTrigger/index.ts b/cloud_functions/functions/src/slackOnTrigger/index.ts
deleted file mode 100644
index f5def5dc0..000000000
--- a/cloud_functions/functions/src/slackOnTrigger/index.ts
+++ /dev/null
@@ -1,111 +0,0 @@
-import { firestore } from "firebase-functions";
-import { hasRequiredFields, serverTimestamp, asyncForEach } from "../utils";
-import _config from "../functionConfig"; // generated using generateConfig.ts
-import { db } from "../config";
-const functionConfig: any = _config;
-type SlackOnTriggerConfig = {
- collectionPath: string;
- onCreate: Boolean;
- onUpdate: Boolean;
- onDelete: Boolean;
- requiredFields: string[];
- messageDocGenerator: (
- snapshot:
- | firestore.DocumentSnapshot
- | {
- before: firestore.DocumentSnapshot;
- after: firestore.DocumentSnapshot;
- }
- // db: FirebaseFirestore.Firestore
- ) => Boolean | any;
-};
-const slackOnCreate = (config: SlackOnTriggerConfig) =>
- firestore
- .document(`${config.collectionPath}/{docId}`)
- .onCreate(async (snapshot) => {
- try {
- const snapshotData = snapshot.data();
- if (!snapshotData) throw Error("no snapshot data");
- const hasAllRequiredFields = hasRequiredFields(
- config.requiredFields,
- snapshotData
- );
- if (hasAllRequiredFields) {
- const messageDoc = await config.messageDocGenerator(snapshot);
- if (messageDoc && typeof messageDoc === "object") {
- await db
- .collection("slackBotMessages")
- .add({ createdAt: serverTimestamp(), ...messageDoc });
- return true;
- } else {
- console.log("message is not sent");
- return false;
- }
- } else {
- console.log("requirements were not met");
- return false;
- }
- } catch (error) {
- console.warn(JSON.stringify(error.response.body));
- return false;
- }
- });
-
-const slackOnUpdate = (config: SlackOnTriggerConfig) =>
- firestore
- .document(`${config.collectionPath}/{docId}`)
- .onUpdate(async (change) => {
- try {
- const beforeData = change.before.data();
- const afterData = change.after.data();
- if (!beforeData || !afterData) throw Error("no data found in snapshot");
- const hasAllRequiredFields = hasRequiredFields(
- config.requiredFields,
- afterData
- );
- if (hasAllRequiredFields) {
- const messageDoc = await config.messageDocGenerator(change);
- console.log({ messageDoc });
- if (
- (messageDoc && typeof messageDoc === "object") ||
- Array.isArray(messageDoc)
- ) {
- console.log("creating slack message doc");
- if (Array.isArray(messageDoc)) {
- await asyncForEach(messageDoc, async (message) => {
- await db
- .collection("slackBotMessages")
- .add({ createdAt: serverTimestamp(), ...message });
- });
- } else {
- await db
- .collection("slackBotMessages")
- .add({ createdAt: serverTimestamp(), ...messageDoc });
- }
-
- return true;
- } else {
- console.log("message is not sent");
- return false;
- }
- } else {
- console.log("requirements were not met");
- return false;
- }
- } catch (error) {
- console.warn(error);
- return false;
- }
- });
-
-const slackOnTriggerFns = (config: SlackOnTriggerConfig) =>
- Object.entries({
- onCreate: config.onCreate ? slackOnCreate(config) : null,
- onUpdate: config.onUpdate ? slackOnUpdate(config) : null,
- }).reduce((a, [k, v]) => (v === null ? a : { ...a, [k]: v }), {});
-
-export const FT_slack = {
- [`${`${functionConfig.collectionPath}`
- .replace(/\//g, "_")
- .replace(/_{.*?}_/g, "_")}`]: slackOnTriggerFns(functionConfig),
-};
diff --git a/cloud_functions/functions/src/slackOnTrigger/trigger.ts b/cloud_functions/functions/src/slackOnTrigger/trigger.ts
deleted file mode 100644
index 2c312e654..000000000
--- a/cloud_functions/functions/src/slackOnTrigger/trigger.ts
+++ /dev/null
@@ -1,103 +0,0 @@
-import { firestore } from "firebase-functions";
-
-import { env } from "../config";
-import { WebClient } from "@slack/web-api";
-import { asyncForEach, serverTimestamp } from "../utils";
-// Initialize
-const web = new WebClient(env.slackbot ? env.slackbot.token : "NEEDS_CONFIG");
-
-const messageByChannel = async ({
- text,
- channel,
- blocks,
- attachments,
-}: {
- channel: string;
- text: string;
- blocks: any[];
- attachments: any[];
-}) =>
- await web.chat.postMessage({
- link_names: true,
- text,
- channel,
- blocks,
- attachments,
- });
-const messageByEmail = async ({
- email,
- text,
- blocks,
- attachments,
-}: {
- email: string;
- text: string;
- blocks: any[];
- attachments: any[];
-}) => {
- try {
- const user = await web.users.lookupByEmail({ email });
- if (user.ok) {
- const channel = (user as any).user.id as string;
- return await messageByChannel({
- text,
- blocks,
- attachments,
- channel,
- });
- } else {
- return await false;
- }
- } catch (error) {
- console.log(`${error} maybe${email} is not on slack`);
- console.log(`${error}`);
- return await false;
- }
-};
-
-export const slackBotMessageOnCreate = firestore
- .document(`slackBotMessages/{docId}`)
- .onCreate(async (snapshot) => {
- const docData = snapshot.data();
- if (!docData) {
- return snapshot.ref.update({
- delivered: false,
- error: "undefined doc",
- });
- }
- try {
- const channels = docData.channel ? [docData.channel] : docData.channels;
- const emails = docData.email ? [docData.email] : docData.emails;
- if (channels) {
- await asyncForEach(channels, async (channel: string) => {
- await messageByChannel({
- text: docData.text,
- blocks: docData.blocks,
- attachments: docData.attachments,
- channel,
- });
- });
- } else if (emails) {
- await asyncForEach(emails, async (email: string) => {
- await messageByEmail({
- text: docData.text,
- blocks: docData.blocks ?? [],
- attachments: docData.attachments ?? [],
- email,
- });
- });
- }
-
- return snapshot.ref.update({
- delivered: true,
- updatedAt: serverTimestamp(),
- });
- } catch (error) {
- console.log(error);
- return snapshot.ref.update({
- delivered: false,
- updatedAt: serverTimestamp(),
- error: JSON.stringify(error),
- });
- }
- });
diff --git a/cloud_functions/functions/src/snapshotSync/index.ts b/cloud_functions/functions/src/snapshotSync/index.ts
deleted file mode 100644
index 9591dbee3..000000000
--- a/cloud_functions/functions/src/snapshotSync/index.ts
+++ /dev/null
@@ -1,205 +0,0 @@
-import * as functions from "firebase-functions";
-
-import { db } from "../config";
-
-import * as _ from "lodash";
-import { replacer, identifyTriggerType } from "../utils";
-
-import Config from "../functionConfig"; // generated using generateConfig.ts
-const functionConfig: any = Config;
-
-enum TargetTypes {
- subCollection = "subCollection",
- document = "document",
-}
-/**
- * returns object with only keys included in fieldsToSync
- * @param docData
- */
-const docReducer = (docData: FirebaseFirestore.DocumentData) => (
- acc: any,
- curr: string
-) => {
- if (docData[curr] !== undefined && docData[curr] !== null) {
- return { ...acc, [curr]: docData[curr] };
- } else return acc;
-};
-
-/**
- *
- * @param targetPath
- * @param fieldsToSync
- */
-const syncSubCollection = async (
- targetPath: string,
- snapshotField: string,
- syncData: any,
- snapshot: FirebaseFirestore.DocumentSnapshot
-) => {
- const targetDocs = await db.collection(targetPath).get();
- if (targetDocs.empty) return false;
- for (const doc of targetDocs.docs) {
- await doc.ref.update({
- [snapshotField]: {
- docPath: snapshot.ref.path,
- snapshot: syncData,
- },
- });
- }
- return true;
-};
-
-const syncDocSnapshot = async (
- targetPath,
- isArray,
- snapshotField,
- newSnapshotData,
- snapshot
-) => {
- console.log({
- targetPath,
- isArray,
- snapshotField,
- });
- const targetRef = db.doc(targetPath);
- const targetSnapshot = await targetRef.get();
- const targetData = targetSnapshot.data();
- if (!targetData) {
- console.warn("target does not exist");
- return false;
- }
-
- if (isArray) {
- const oldSnapshotsArray = targetData[snapshotField];
- if (!oldSnapshotsArray) {
- return targetRef.update({
- [snapshotField]: [
- { docPath: snapshot.ref.path, snapshot: newSnapshotData },
- ],
- });
- } else {
- const snapshotDocPath = snapshot.ref.path;
- const oldSnapshot = _.find(oldSnapshotsArray, {
- docPath: snapshotDocPath,
- });
- if (oldSnapshot) {
- return targetRef.update({
- [snapshotField]: oldSnapshotsArray.map(
- (item: { docPath: string; snapshot: any }) => {
- if (item.docPath === snapshotDocPath) {
- return {
- ...oldSnapshot,
- docPath: snapshotDocPath,
- snapshot: newSnapshotData,
- };
- } else return item;
- }
- ),
- });
- } else {
- return targetRef.update({
- [snapshotField]: [
- ...oldSnapshotsArray,
- { docPath: snapshotDocPath, snapshot: newSnapshotData },
- ],
- });
- }
- }
- } else {
- return targetRef.update({
- [snapshotField]: {
- ...targetData[snapshotField],
- snapshot: newSnapshotData,
- },
- });
- }
-};
-
-/**
- * onUpdate change to snapshot adapter
- * @param targetCollection
- * @param fieldsToSync
- */
-const syncDocOnWrite = (config: {
- target: string;
- snapshotField: string;
- targetType: TargetTypes;
- fieldsToSync: string[];
- isArray: boolean;
-}) => (snapshot: functions.Change) => {
- const { fieldsToSync, target, snapshotField, targetType, isArray } = config;
-
- const afterDocData = snapshot.after.data();
- const beforeDocData = snapshot.before.data();
-
- const triggerType = identifyTriggerType(beforeDocData, afterDocData);
-
- const afterData = fieldsToSync.reduce(docReducer(afterDocData ?? {}), {});
- const beforeData = fieldsToSync.reduce(docReducer(beforeDocData ?? {}), {});
- const hasChanged = !_.isEqual(afterData, beforeData);
- console.log("nothing important changed");
- if (Object.keys(afterData).length === 0) return false; // returns if theres nothing to sync
-
- const targetPath = target.replace(
- /\{\{(.*?)\}\}/g,
- replacer({ ...snapshot.after.data(), id: snapshot.after.id })
- );
- console.log({ targetPath });
- if (targetPath === "") {
- console.log("unspecified target");
- return false;
- }
- console.log({ hasChanged, targetType });
- if (hasChanged) {
- switch (targetType) {
- case TargetTypes.subCollection:
- return triggerType === "update"
- ? syncSubCollection(
- targetPath,
- snapshotField,
- { ...afterData, objectID: snapshot.after.ref.id },
- snapshot.after
- )
- : false;
-
- case TargetTypes.document:
- return triggerType !== "delete"
- ? syncDocSnapshot(
- targetPath,
- isArray,
- snapshotField,
- { ...afterData, objectID: snapshot.after.ref.id },
- snapshot.after
- )
- : false;
- default:
- return false;
- }
- } else {
- console.warn("no change detected");
- return false;
- }
-};
-
-/**
- * returns 2 different trigger functions (onCreate,onUpdate) in an object
- * @param config configuration object
- */
-const snapshotSyncFnsGenerator = (config) =>
- functions.firestore
- .document(`${config.source}/{docId}`)
- .onWrite(syncDocOnWrite(config));
-
-//export default snapshotSyncFnsGenerator;
-
-export const FT_snapshotSync = functionConfig.fnName
- ? { [functionConfig.fnName]: snapshotSyncFnsGenerator(functionConfig) }
- : {
- [`${`${`${functionConfig.source}`
- .replace(/\//g, "_")
- .replace(/_{.*?}_/g, "_")}`}2${`${`${functionConfig.target}`
- .replace(/\//g, "_")
- .replace(/_{.*?}_/g, "_")}`}`]: snapshotSyncFnsGenerator(
- functionConfig
- ),
- };
diff --git a/cloud_functions/functions/src/subTableStats.ts b/cloud_functions/functions/src/subTableStats.ts
deleted file mode 100644
index 8da27b14b..000000000
--- a/cloud_functions/functions/src/subTableStats.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import * as functions from "firebase-functions";
-import * as admin from "firebase-admin";
-
-import { collectionPath } from "./functionConfig"; // generated using generateConfig.ts
-const increment = admin.firestore.FieldValue.increment(1);
-const decrement = admin.firestore.FieldValue.increment(-1);
-const docCreated = (
- snapshot: functions.firestore.DocumentSnapshot,
- context: functions.EventContext
-) => {
- const { subCollectionId } = context.params;
- return snapshot.ref.parent.parent?.update({
- [`${subCollectionId}.count`]: increment,
- });
-};
-
-const docDelete = (
- snapshot: functions.firestore.DocumentSnapshot,
- context: functions.EventContext
-) => {
- const { subCollectionId } = context.params;
- return snapshot.ref.parent.parent?.update({
- [subCollectionId]: decrement,
- });
-};
-const subTableFnsGenerator = {
- onCreate: functions.firestore
- .document(`${collectionPath}/{parentId}/{subCollectionId}/{docId}`)
- .onCreate(docCreated),
- onDelete: functions.firestore
- .document(`${collectionPath}/{parentId}/{subCollectionId}/{docId}`)
- .onDelete(docDelete),
-};
-
-export const FT_subTableStats = {
- [collectionPath]: { ...subTableFnsGenerator },
-};
diff --git a/cloud_functions/functions/src/utils/auth.ts b/cloud_functions/functions/src/utils/auth.ts
deleted file mode 100644
index 67857e2ae..000000000
--- a/cloud_functions/functions/src/utils/auth.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import * as functions from "firebase-functions";
-
-export const hasAnyRole = (
- authorizedRoles: string[],
- context: functions.https.CallableContext
-) => {
- if (!context.auth || !context.auth.token.roles) return false;
- const userRoles = context.auth.token.roles as string[];
- const authorization = authorizedRoles.reduce(
- (authorized: boolean, role: string) => {
- if (userRoles.includes(role)) return true;
- else return authorized;
- },
- false
- );
- return authorization;
-};
diff --git a/cloud_functions/functions/src/utils/email.ts b/cloud_functions/functions/src/utils/email.ts
deleted file mode 100644
index 83e817be6..000000000
--- a/cloud_functions/functions/src/utils/email.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-const sgMail = require("@sendgrid/mail");
-import { env } from "../config";
-sgMail.setSubstitutionWrappers("{{", "}}");
-if (env.send_grid) sgMail.setApiKey(env.send_grid.key);
-
-export const sendEmail = (msg: any) => sgMail.send(msg);
diff --git a/cloud_functions/functions/src/utils/index.ts b/cloud_functions/functions/src/utils/index.ts
deleted file mode 100644
index 82cea1908..000000000
--- a/cloud_functions/functions/src/utils/index.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import * as admin from "firebase-admin";
-import * as _ from "lodash";
-export const serverTimestamp = admin.firestore.FieldValue.serverTimestamp;
-import { sendEmail } from "./email";
-import { hasAnyRole } from "./auth";
-
-const characters =
- "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
-export function generateId(length) {
- let result = "";
- const charactersLength = characters.length;
- for (let i = 0; i < length; i++) {
- result += characters.charAt(Math.floor(Math.random() * charactersLength));
- }
- return result;
-}
-
-export default { generateId, sendEmail, serverTimestamp, hasAnyRole };
-export const replacer = (data: any) => (m: string, key: string) => {
- const objKey = key.split(":")[0];
- const defaultValue = key.split(":")[1] || "";
- return _.get(data, objKey, defaultValue);
-};
-
-export const hasRequiredFields = (requiredFields: string[], data: any) =>
- requiredFields.reduce((acc: boolean, currField: string) => {
- if (data[currField] === undefined || data[currField] === null) return false;
- else return acc;
- }, true);
-export async function asyncForEach(array: any[], callback: Function) {
- for (let index = 0; index < array.length; index++) {
- await callback(array[index], index, array);
- }
-}
-
-export const identifyTriggerType = (beforeData, afterData) =>
- Boolean(beforeData) && Boolean(afterData)
- ? "update"
- : Boolean(afterData)
- ? "create"
- : "delete";
diff --git a/cloud_functions/functions/src/webhooks/index.ts b/cloud_functions/functions/src/webhooks/index.ts
deleted file mode 100644
index d48b0ccf0..000000000
--- a/cloud_functions/functions/src/webhooks/index.ts
+++ /dev/null
@@ -1,84 +0,0 @@
-import { db } from "../config";
-import * as functions from "firebase-functions";
-// const fetch = require("node-fetch");
-
-//import * as crypto from "crypto";
-
-//const TYPEFORM_SECRET = "testsecret123";
-//const verifySignature = function (secret, receivedSignature, payload) {
-// const hash = crypto
-// .createHmac("sha256", secret)
-// .update(payload)
-// .digest("base64");
-// console.log(receivedSignature, `sha256=${hash}`);
-// return receivedSignature === `sha256=${hash}`;
-// };
-
-//const file = bucket.file('path/to/image.jpg');
-
-const typeformParser = (body) => ({
- _ft_createdAt: body.form_response.submitted_at,
- ...body.form_response.hidden,
- ...body.form_response.answers.reduce((accRow, currAnswer) => {
- switch (currAnswer.type) {
- case "date":
- return {
- ...accRow,
- [currAnswer.field.ref]: new Date(currAnswer[currAnswer.type]),
- };
- case "choice":
- return {
- ...accRow,
- [currAnswer.field.ref]: currAnswer[currAnswer.type].label,
- };
- case "choices":
- return {
- ...accRow,
- [currAnswer.field.ref]: currAnswer[currAnswer.type].labels,
- };
- case "file_url":
- default:
- return {
- ...accRow,
- [currAnswer.field.ref]: currAnswer[currAnswer.type],
- };
- }
- }, {}),
-});
-
-export const webhook = functions.https.onRequest(async (req, res) => {
- const { body, url, query } = req;
- console.log(JSON.stringify({ body, url, query }));
- const schemaDocPath = `_FIRETABLE_/settings/schema/${decodeURIComponent(
- query.tablePath as string
- )}`;
- const schemaDoc = await db.doc(schemaDocPath).get();
- const schemaDocData = schemaDoc.data();
- if (!schemaDocData) {
- res.sendStatus(404);
- }
- if (!schemaDocData?.webhooks.enabled) {
- res.sendStatus(401);
- }
-
- if (query.type === "CUSTOM") {
- console.log({ schemaDocData });
- } else if (query.type === "TYPE_FORM") {
- // const receivedSignature = req.header("Typeform-Signature");
- const secret = schemaDocData?.webhooks.secret;
- // const isValidSignature = verifySignature(
- // TYPEFORM_SECRET,
- // receivedSignature,
- // req.body.toString()
- // );
- if (req.query.secret === secret) {
- const newRow = typeformParser(req.body);
- await db
- .collection(decodeURIComponent(req.query.tablePath as string))
- .add(newRow);
- } else {
- res.sendStatus(403);
- }
- }
- res.sendStatus(200);
-});
diff --git a/cloud_functions/functions/tsconfig.json b/cloud_functions/functions/tsconfig.json
deleted file mode 100644
index 76e18cb1d..000000000
--- a/cloud_functions/functions/tsconfig.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "compilerOptions": {
- "module": "commonjs",
- "noImplicitReturns": true,
- "noUnusedLocals": true,
- "outDir": "lib",
- "sourceMap": true,
- "strict": true,
- "noImplicitAny": false,
- "resolveJsonModule": true,
- "target": "es2017"
- },
- "compileOnSave": true,
- "include": ["src", "generateConfig.ts"]
-}
diff --git a/cloud_functions/functions/tslint.json b/cloud_functions/functions/tslint.json
deleted file mode 100644
index e28661855..000000000
--- a/cloud_functions/functions/tslint.json
+++ /dev/null
@@ -1,119 +0,0 @@
-{
- "rules": {
- // -- Strict errors --
- // These lint rules are likely always a good idea.
-
- // Force function overloads to be declared together. This ensures readers understand APIs.
- "adjacent-overload-signatures": true,
-
- // Do not allow the subtle/obscure comma operator.
- "ban-comma-operator": true,
-
- // Do not allow internal modules or namespaces . These are deprecated in favor of ES6 modules.
- "no-namespace": true,
-
- // Do not allow parameters to be reassigned. To avoid bugs, developers should instead assign new values to new vars.
- "no-parameter-reassignment": true,
-
- // Force the use of ES6-style imports instead of /// imports.
- "no-reference": true,
-
- // Do not allow type assertions that do nothing. This is a big warning that the developer may not understand the
- // code currently being edited (they may be incorrectly handling a different type case that does not exist).
- "no-unnecessary-type-assertion": true,
-
- // Disallow nonsensical label usage.
- "label-position": true,
-
- // Disallows the (often typo) syntax if (var1 = var2). Replace with if (var2) { var1 = var2 }.
- "no-conditional-assignment": true,
-
- // Disallows constructors for primitive types (e.g. new Number('123'), though Number('123') is still allowed).
- "no-construct": true,
-
- // Do not allow super() to be called twice in a constructor.
- "no-duplicate-super": true,
-
- // Do not allow the same case to appear more than once in a switch block.
- "no-duplicate-switch-case": true,
-
- // Do not allow a variable to be declared more than once in the same block. Consider function parameters in this
- // rule.
- "no-duplicate-variable": [true, "check-parameters"],
-
- // Disallows a variable definition in an inner scope from shadowing a variable in an outer scope. Developers should
- // instead use a separate variable name.
- "no-shadowed-variable": true,
-
- // Empty blocks are almost never needed. Allow the one general exception: empty catch blocks.
- "no-empty": [true, "allow-empty-catch"],
-
- // Functions must either be handled directly (e.g. with a catch() handler) or returned to another function.
- // This is a major source of errors in Cloud Functions and the team strongly recommends leaving this rule on.
- "no-floating-promises": true,
-
- // Do not allow any imports for modules that are not in package.json. These will almost certainly fail when
- // deployed.
- "no-implicit-dependencies": true,
-
- // The 'this' keyword can only be used inside of classes.
- "no-invalid-this": true,
-
- // Do not allow strings to be thrown because they will not include stack traces. Throw Errors instead.
- "no-string-throw": true,
-
- // Disallow control flow statements, such as return, continue, break, and throw in finally blocks.
- "no-unsafe-finally": true,
-
- // Do not allow variables to be used before they are declared.
- "no-use-before-declare": true,
-
- // Expressions must always return a value. Avoids common errors like const myValue = functionReturningVoid();
- "no-void-expression": [true, "ignore-arrow-function-shorthand"],
-
- // Disallow duplicate imports in the same file.
- "no-duplicate-imports": true,
-
- // -- Strong Warnings --
- // These rules should almost never be needed, but may be included due to legacy code.
- // They are left as a warning to avoid frustration with blocked deploys when the developer
- // understand the warning and wants to deploy anyway.
-
- // Warn when an empty interface is defined. These are generally not useful.
- "no-empty-interface": { "severity": "warning" },
-
- // Warn when an import will have side effects.
- "no-import-side-effect": { "severity": "warning" },
-
- // Warn when variables are defined with var. Var has subtle meaning that can lead to bugs. Strongly prefer const for
- // most values and let for values that will change.
- "no-var-keyword": { "severity": "warning" },
-
- // Prefer === and !== over == and !=. The latter operators support overloads that are often accidental.
- "triple-equals": { "severity": "warning" },
-
- // Warn when using deprecated APIs.
- "deprecation": { "severity": "warning" },
-
- // -- Light Warnings --
- // These rules are intended to help developers use better style. Simpler code has fewer bugs. These would be "info"
- // if TSLint supported such a level.
-
- // prefer for( ... of ... ) to an index loop when the index is only used to fetch an object from an array.
- // (Even better: check out utils like .map if transforming an array!)
- "prefer-for-of": { "severity": "warning" },
-
- // Warns if function overloads could be unified into a single function with optional or rest parameters.
- "unified-signatures": { "severity": "warning" },
-
- // Prefer const for values that will not change. This better documents code.
- "prefer-const": { "severity": "warning" },
-
- // Multi-line object literals and function calls should have a trailing comma. This helps avoid merge conflicts.
- "trailing-comma": { "severity": "warning" }
- },
- "linterOptions": {
- "exclude": ["./generator/templates/**"]
- },
- "defaultSeverity": "error"
-}
diff --git a/cloud_functions/functions/updateDeployStatus.ts b/cloud_functions/functions/updateDeployStatus.ts
deleted file mode 100644
index 166b8b70b..000000000
--- a/cloud_functions/functions/updateDeployStatus.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-// Initialize Firebase Admin
-import * as admin from "firebase-admin";
-// Initialize Firebase Admin
-const serverTimestamp = admin.firestore.FieldValue.serverTimestamp;
-admin.initializeApp();
-const db = admin.firestore();
-
-const main = async (deployRequestPath: string, currentBuild) => {
- await db.doc(deployRequestPath).update({
- deployedAt: serverTimestamp(),
- currentBuild: currentBuild ?? "",
- });
- return true;
-};
-
-main(process.argv[2], process.argv[3])
- .catch((err) => console.log(err))
- .then(() => console.log("this will succeed"))
- .catch(() => "obligatory catch");
diff --git a/cloud_functions/functions/yarn.lock b/cloud_functions/functions/yarn.lock
deleted file mode 100644
index 8d57081d8..000000000
--- a/cloud_functions/functions/yarn.lock
+++ /dev/null
@@ -1,6576 +0,0 @@
-# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
-# yarn lockfile v1
-
-
-"@algolia/cache-browser-local-storage@4.8.6":
- version "4.8.6"
- resolved "https://registry.yarnpkg.com/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.8.6.tgz#6be9644b68efbbc231ac3f0a4cfa985ef31eade9"
- integrity sha512-Bam7otzjIEgrRXWmk0Amm1+B3ROI5dQnUfJEBjIy0YPM0kMahEoJXCw6160tGKxJLl1g6icoC953nGshQKO7cA==
- dependencies:
- "@algolia/cache-common" "4.8.6"
-
-"@algolia/cache-common@4.8.6":
- version "4.8.6"
- resolved "https://registry.yarnpkg.com/@algolia/cache-common/-/cache-common-4.8.6.tgz#dff1697a0fe3d7856630071559661ec5ad90f31c"
- integrity sha512-eGQlsXU5G7n4RvV/K6qe6lRAeL6EKAYPT3yZDBjCW4pAh7JWta+77a7BwUQkTqXN1MEQWZXjex3E4z/vFpzNrg==
-
-"@algolia/cache-in-memory@4.8.6":
- version "4.8.6"
- resolved "https://registry.yarnpkg.com/@algolia/cache-in-memory/-/cache-in-memory-4.8.6.tgz#9a100a1be05e700a253ef4bdabd3bd45df2f67d4"
- integrity sha512-kbJrvCFANxL/l5Pq1NFyHLRphKDwmqcD/OJga0IbNKEulRGDPkt1+pC7/q8d2ikP12adBjLLg2CVias9RJpIaw==
- dependencies:
- "@algolia/cache-common" "4.8.6"
-
-"@algolia/client-account@4.8.6":
- version "4.8.6"
- resolved "https://registry.yarnpkg.com/@algolia/client-account/-/client-account-4.8.6.tgz#050cfd6a6d3e06a5a8e1029f24d6d50524d186c6"
- integrity sha512-FQVJE/BgCb78jtG7V0r30sMl9P5JKsrsOacGtGF2YebqI0YF25y8Z1nO39lbdjahxUS3QkDw2d0P2EVMj65g2Q==
- dependencies:
- "@algolia/client-common" "4.8.6"
- "@algolia/client-search" "4.8.6"
- "@algolia/transporter" "4.8.6"
-
-"@algolia/client-analytics@4.8.6":
- version "4.8.6"
- resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-4.8.6.tgz#ac644cfc9d87a085b9e53c71a42ef6e90d828501"
- integrity sha512-ZBYFUlzNaWDFtt0rYHI7xbfVX0lPWU9lcEEXI/BlnkRgEkm247H503tNatPQFA1YGkob52EU18sV1eJ+OFRBLA==
- dependencies:
- "@algolia/client-common" "4.8.6"
- "@algolia/client-search" "4.8.6"
- "@algolia/requester-common" "4.8.6"
- "@algolia/transporter" "4.8.6"
-
-"@algolia/client-common@4.8.6":
- version "4.8.6"
- resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-4.8.6.tgz#c8b81af250ed8beb741a0e5cfdd3236bb4292c94"
- integrity sha512-8dI+K3Nvbes2YRZm2LY7bdCUD05e60BhacrMLxFuKxnBGuNehME1wbxq/QxcG1iNFJlxLIze5TxIcNN3+pn76g==
- dependencies:
- "@algolia/requester-common" "4.8.6"
- "@algolia/transporter" "4.8.6"
-
-"@algolia/client-recommendation@4.8.6":
- version "4.8.6"
- resolved "https://registry.yarnpkg.com/@algolia/client-recommendation/-/client-recommendation-4.8.6.tgz#2518a09bfbeaec78b0d7a4213107f0899f80f9ac"
- integrity sha512-Kg8DpjwvaWWujNx6sAUrSL+NTHxFe/UNaliCcSKaMhd3+FiPXN+CrSkO0KWR7I+oK2qGBTG/2Y0BhFOJ5/B/RA==
- dependencies:
- "@algolia/client-common" "4.8.6"
- "@algolia/requester-common" "4.8.6"
- "@algolia/transporter" "4.8.6"
-
-"@algolia/client-search@4.8.6":
- version "4.8.6"
- resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-4.8.6.tgz#1ca3f28c04ef4120b0563a293b30fcfe1b3fd1d0"
- integrity sha512-vXLS6umL/9G3bwqc6pkrS9K5/s8coq55mpfRARL+bs0NsToOf77WSTdwzlxv/KdbVF7dHjXgUpBvJ6RyR4ZdAw==
- dependencies:
- "@algolia/client-common" "4.8.6"
- "@algolia/requester-common" "4.8.6"
- "@algolia/transporter" "4.8.6"
-
-"@algolia/logger-common@4.8.6":
- version "4.8.6"
- resolved "https://registry.yarnpkg.com/@algolia/logger-common/-/logger-common-4.8.6.tgz#8c44a4f550e12418b0ec8d76a068e4f1c64206d1"
- integrity sha512-FMRxZGdDxSzd0/Mv0R1021FvUt0CcbsQLYeyckvSWX8w+Uk4o0lcV6UtZdERVR5XZsGOqoXLMIYDbR2vkbGbVw==
-
-"@algolia/logger-console@4.8.6":
- version "4.8.6"
- resolved "https://registry.yarnpkg.com/@algolia/logger-console/-/logger-console-4.8.6.tgz#77176570fa6532fa846c7cfa2c6280935b1a3a06"
- integrity sha512-TYw9lwUCjvApC6Z0zn36T6gkCl7hbfJmnU+Z/D8pFJ3Yp7lz06S3oWGjbdrULrYP1w1VOhjd0X7/yGNsMhzutQ==
- dependencies:
- "@algolia/logger-common" "4.8.6"
-
-"@algolia/requester-browser-xhr@4.8.6":
- version "4.8.6"
- resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.8.6.tgz#dbcb5906d10c619d7f08fced2f68fa09abffe5fd"
- integrity sha512-omh6uJ3CJXOmcrU9M3/KfGg8XkUuGJGIMkqEbkFvIebpBJxfs6TVs0ziNeMFAcAfhi8/CGgpLbDSgJtWdGQa6w==
- dependencies:
- "@algolia/requester-common" "4.8.6"
-
-"@algolia/requester-common@4.8.6":
- version "4.8.6"
- resolved "https://registry.yarnpkg.com/@algolia/requester-common/-/requester-common-4.8.6.tgz#37ea1f9ecc1afcd91532b9f9c952c62fdef42bca"
- integrity sha512-r5xJqq/D9KACkI5DgRbrysVL5DUUagikpciH0k0zjBbm+cXiYfpmdflo/h6JnY6kmvWgjr/4DoeTjKYb/0deAQ==
-
-"@algolia/requester-node-http@4.8.6":
- version "4.8.6"
- resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-4.8.6.tgz#e966293224f3bd1ba32ce4f9bc0fdada5d8e69ec"
- integrity sha512-TB36OqTVOKyHCOtdxhn/IJyI/NXi/BWy8IEbsiWwwZWlL79NWHbetj49jXWFolEYEuu8PgDjjZGpRhypSuO9XQ==
- dependencies:
- "@algolia/requester-common" "4.8.6"
-
-"@algolia/transporter@4.8.6":
- version "4.8.6"
- resolved "https://registry.yarnpkg.com/@algolia/transporter/-/transporter-4.8.6.tgz#b605dcd971aed374bdd95dd8938b93b9df650109"
- integrity sha512-NRb31J0TP7EPoVMpXZ4yAtr61d26R8KGaf6qdULknvq5sOVHuuH4PwmF08386ERfIsgnM/OBhl+uzwACdCIjSg==
- dependencies:
- "@algolia/cache-common" "4.8.6"
- "@algolia/logger-common" "4.8.6"
- "@algolia/requester-common" "4.8.6"
-
-"@apidevtools/json-schema-ref-parser@^9.0.3":
- version "9.0.7"
- resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.7.tgz#64aa7f5b34e43d74ea9e408b90ddfba02050dde3"
- integrity sha512-QdwOGF1+eeyFh+17v2Tz626WX0nucd1iKOm6JUTUvCZdbolblCOOQCxGrQPY0f7jEhn36PiAWqZnsC2r5vmUWg==
- dependencies:
- "@jsdevtools/ono" "^7.1.3"
- call-me-maybe "^1.0.1"
- js-yaml "^3.13.1"
-
-"@babel/code-frame@^7.0.0":
- version "7.12.11"
- resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f"
- integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==
- dependencies:
- "@babel/highlight" "^7.10.4"
-
-"@babel/helper-validator-identifier@^7.10.4":
- version "7.12.11"
- resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed"
- integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==
-
-"@babel/highlight@^7.10.4":
- version "7.10.4"
- resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143"
- integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==
- dependencies:
- "@babel/helper-validator-identifier" "^7.10.4"
- chalk "^2.0.0"
- js-tokens "^4.0.0"
-
-"@dabh/diagnostics@^2.0.2":
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.2.tgz#290d08f7b381b8f94607dc8f471a12c675f9db31"
- integrity sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==
- dependencies:
- colorspace "1.1.x"
- enabled "2.0.x"
- kuler "^2.0.0"
-
-"@firebase/app-types@0.6.1":
- version "0.6.1"
- resolved "https://registry.yarnpkg.com/@firebase/app-types/-/app-types-0.6.1.tgz#dcbd23030a71c0c74fc95d4a3f75ba81653850e9"
- integrity sha512-L/ZnJRAq7F++utfuoTKX4CLBG5YR7tFO3PLzG1/oXXKEezJ0kRL3CMRoueBEmTCzVb/6SIs2Qlaw++uDgi5Xyg==
-
-"@firebase/auth-interop-types@0.1.5":
- version "0.1.5"
- resolved "https://registry.yarnpkg.com/@firebase/auth-interop-types/-/auth-interop-types-0.1.5.tgz#9fc9bd7c879f16b8d1bb08373a0f48c3a8b74557"
- integrity sha512-88h74TMQ6wXChPA6h9Q3E1Jg6TkTHep2+k63OWg3s0ozyGVMeY+TTOti7PFPzq5RhszQPQOoCi59es4MaRvgCw==
-
-"@firebase/component@0.1.21":
- version "0.1.21"
- resolved "https://registry.yarnpkg.com/@firebase/component/-/component-0.1.21.tgz#56062eb0d449dc1e7bbef3c084a9b5fa48c7c14d"
- integrity sha512-kd5sVmCLB95EK81Pj+yDTea8pzN2qo/1yr0ua9yVi6UgMzm6zAeih73iVUkaat96MAHy26yosMufkvd3zC4IKg==
- dependencies:
- "@firebase/util" "0.3.4"
- tslib "^1.11.1"
-
-"@firebase/database-types@0.6.1", "@firebase/database-types@^0.6.1":
- version "0.6.1"
- resolved "https://registry.yarnpkg.com/@firebase/database-types/-/database-types-0.6.1.tgz#cf1cfc03e617ed4c2561703781f85ba4c707ff65"
- integrity sha512-JtL3FUbWG+bM59iYuphfx9WOu2Mzf0OZNaqWiQ7lJR8wBe7bS9rIm9jlBFtksB7xcya1lZSQPA/GAy2jIlMIkA==
- dependencies:
- "@firebase/app-types" "0.6.1"
-
-"@firebase/database@^0.8.1":
- version "0.8.3"
- resolved "https://registry.yarnpkg.com/@firebase/database/-/database-0.8.3.tgz#4e5efa8fc8df00d6febfd9c8d6d6e409596659f7"
- integrity sha512-i29rr3kcPltIkA8La9M1lgsSxx9bfu5lCQ0T+tbJptZ3UpqpcL1NzCcZa24cJjiLgq3HQNPyLvUvCtcPSFDlRg==
- dependencies:
- "@firebase/auth-interop-types" "0.1.5"
- "@firebase/component" "0.1.21"
- "@firebase/database-types" "0.6.1"
- "@firebase/logger" "0.2.6"
- "@firebase/util" "0.3.4"
- faye-websocket "0.11.3"
- tslib "^1.11.1"
-
-"@firebase/logger@0.2.6":
- version "0.2.6"
- resolved "https://registry.yarnpkg.com/@firebase/logger/-/logger-0.2.6.tgz#3aa2ca4fe10327cabf7808bd3994e88db26d7989"
- integrity sha512-KIxcUvW/cRGWlzK9Vd2KB864HlUnCfdTH0taHE0sXW5Xl7+W68suaeau1oKNEqmc3l45azkd4NzXTCWZRZdXrw==
-
-"@firebase/util@0.3.4":
- version "0.3.4"
- resolved "https://registry.yarnpkg.com/@firebase/util/-/util-0.3.4.tgz#e389d0e0e2aac88a5235b06ba9431db999d4892b"
- integrity sha512-VwjJUE2Vgr2UMfH63ZtIX9Hd7x+6gayi6RUXaTqEYxSbf/JmehLmAEYSuxS/NckfzAXWeGnKclvnXVibDgpjQQ==
- dependencies:
- tslib "^1.11.1"
-
-"@google-cloud/cloudbuild@^2.0.6":
- version "2.0.6"
- resolved "https://registry.yarnpkg.com/@google-cloud/cloudbuild/-/cloudbuild-2.0.6.tgz#21822ced372c5c488f4c2773b8f07d71da852785"
- integrity sha512-hKJPGuy/K6E15CZ8wH8j7k1suQCYisbKJPY6NN32+QoB81OHp/TwKc2vv3FeUASV2rvGDzhEkfAZHDWQ8my1FA==
- dependencies:
- google-gax "^2.9.2"
-
-"@google-cloud/common@^3.5.0":
- version "3.5.0"
- resolved "https://registry.yarnpkg.com/@google-cloud/common/-/common-3.5.0.tgz#0959e769e8075a06eb0823cc567eef00fd0c2d02"
- integrity sha512-10d7ZAvKhq47L271AqvHEd8KzJqGU45TY+rwM2Z3JHuB070FeTi7oJJd7elfrnKaEvaktw3hH2wKnRWxk/3oWQ==
- dependencies:
- "@google-cloud/projectify" "^2.0.0"
- "@google-cloud/promisify" "^2.0.0"
- arrify "^2.0.1"
- duplexify "^4.1.1"
- ent "^2.2.0"
- extend "^3.0.2"
- google-auth-library "^6.1.1"
- retry-request "^4.1.1"
- teeny-request "^7.0.0"
-
-"@google-cloud/firestore@^4.5.0", "@google-cloud/firestore@^4.9.7":
- version "4.9.7"
- resolved "https://registry.yarnpkg.com/@google-cloud/firestore/-/firestore-4.9.7.tgz#8fb9080ba0f6e074013412835b60db926515d139"
- integrity sha512-s5W6rRxD5y3Oe3KJUNztIy4eIi9dBwJU36jd/QM3L8frpCuSh1fn6z0BD8IAV0AirQAg6aOzSlcwAwd/yeXCkw==
- dependencies:
- fast-deep-equal "^3.1.1"
- functional-red-black-tree "^1.0.1"
- google-gax "^2.9.2"
- protobufjs "^6.8.6"
-
-"@google-cloud/paginator@^3.0.0":
- version "3.0.5"
- resolved "https://registry.yarnpkg.com/@google-cloud/paginator/-/paginator-3.0.5.tgz#9d6b96c421a89bd560c1bc2c197c7611ef21db6c"
- integrity sha512-N4Uk4BT1YuskfRhKXBs0n9Lg2YTROZc6IMpkO/8DIHODtm5s3xY8K5vVBo23v/2XulY3azwITQlYWgT4GdLsUw==
- dependencies:
- arrify "^2.0.0"
- extend "^3.0.2"
-
-"@google-cloud/precise-date@^2.0.0":
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/@google-cloud/precise-date/-/precise-date-2.0.3.tgz#14f6f28ce35dabf3882e7aeab1c9d51bd473faed"
- integrity sha512-+SDJ3ZvGkF7hzo6BGa8ZqeK3F6Z4+S+KviC9oOK+XCs3tfMyJCh/4j93XIWINgMMDIh9BgEvlw4306VxlXIlYA==
-
-"@google-cloud/projectify@^2.0.0":
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/@google-cloud/projectify/-/projectify-2.0.1.tgz#13350ee609346435c795bbfe133a08dfeab78d65"
- integrity sha512-ZDG38U/Yy6Zr21LaR3BTiiLtpJl6RkPS/JwoRT453G+6Q1DhlV0waNf8Lfu+YVYGIIxgKnLayJRfYlFJfiI8iQ==
-
-"@google-cloud/promisify@^2.0.0":
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/@google-cloud/promisify/-/promisify-2.0.3.tgz#f934b5cdc939e3c7039ff62b9caaf59a9d89e3a8"
- integrity sha512-d4VSA86eL/AFTe5xtyZX+ePUjE8dIFu2T8zmdeNBSa5/kNgXPCx/o/wbFNHAGLJdGnk1vddRuMESD9HbOC8irw==
-
-"@google-cloud/pubsub@^2.5.0", "@google-cloud/pubsub@^2.7.0":
- version "2.8.0"
- resolved "https://registry.yarnpkg.com/@google-cloud/pubsub/-/pubsub-2.8.0.tgz#143f6c5f7dda1d22bf1ffd98104caf8c2611fca6"
- integrity sha512-AoSKAbpHCoLq6jO9vMX+K6hJhkayafan24Rs2RKHU8Y0qF6IGSm1+ly0OG12TgziHWg818/6dljWWKgwDcp8KA==
- dependencies:
- "@google-cloud/paginator" "^3.0.0"
- "@google-cloud/precise-date" "^2.0.0"
- "@google-cloud/projectify" "^2.0.0"
- "@google-cloud/promisify" "^2.0.0"
- "@opentelemetry/api" "^0.12.0"
- "@opentelemetry/tracing" "^0.12.0"
- "@types/duplexify" "^3.6.0"
- "@types/long" "^4.0.0"
- arrify "^2.0.0"
- extend "^3.0.2"
- google-auth-library "^6.1.2"
- google-gax "^2.9.2"
- is-stream-ended "^0.1.4"
- lodash.snakecase "^4.1.1"
- p-defer "^3.0.0"
-
-"@google-cloud/storage@^5.1.2", "@google-cloud/storage@^5.3.0":
- version "5.7.4"
- resolved "https://registry.yarnpkg.com/@google-cloud/storage/-/storage-5.7.4.tgz#de79c569a2b296e7c85d9141812fbe107a66c1ef"
- integrity sha512-fynB3kDT+lhx71laML+LtUs/w9Ezcf+SVAsaP0fhAyPQzOc0kp43uYTymYCvF9GffYR7jcy6yqYifeMSU9VEVA==
- dependencies:
- "@google-cloud/common" "^3.5.0"
- "@google-cloud/paginator" "^3.0.0"
- "@google-cloud/promisify" "^2.0.0"
- arrify "^2.0.0"
- async-retry "^1.3.1"
- compressible "^2.0.12"
- date-and-time "^0.14.2"
- duplexify "^4.0.0"
- extend "^3.0.2"
- gaxios "^4.0.0"
- gcs-resumable-upload "^3.1.0"
- get-stream "^6.0.0"
- hash-stream-validation "^0.2.2"
- mime "^2.2.0"
- mime-types "^2.0.8"
- onetime "^5.1.0"
- p-limit "^3.0.1"
- pumpify "^2.0.0"
- snakeize "^0.1.0"
- stream-events "^1.0.1"
- xdg-basedir "^4.0.0"
-
-"@grpc/grpc-js@~1.2.0":
- version "1.2.5"
- resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.2.5.tgz#d1ef9ae8b99c3b46bb6cc8c82be1aa80080b7300"
- integrity sha512-CBCNwedw8McnEBq9jvoiJikws16WN0OiHFejQPovY71XkFWSiIqgvydYiDwpvIYDJmhPQ7qZNzW9BPndhXbx1Q==
- dependencies:
- "@types/node" "^12.12.47"
- google-auth-library "^6.1.1"
- semver "^6.2.0"
-
-"@grpc/proto-loader@^0.5.1":
- version "0.5.6"
- resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.5.6.tgz#1dea4b8a6412b05e2d58514d507137b63a52a98d"
- integrity sha512-DT14xgw3PSzPxwS13auTEwxhMMOoz33DPUKNtmYK/QYbBSpLXJy78FGGs5yVoxVobEqPm4iW9MOIoz0A3bLTRQ==
- dependencies:
- lodash.camelcase "^4.3.0"
- protobufjs "^6.8.6"
-
-"@jsdevtools/ono@^7.1.3":
- version "7.1.3"
- resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796"
- integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==
-
-"@nodelib/fs.scandir@2.1.4":
- version "2.1.4"
- resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz#d4b3549a5db5de2683e0c1071ab4f140904bbf69"
- integrity sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==
- dependencies:
- "@nodelib/fs.stat" "2.0.4"
- run-parallel "^1.1.9"
-
-"@nodelib/fs.stat@2.0.4", "@nodelib/fs.stat@^2.0.2":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz#a3f2dd61bab43b8db8fa108a121cfffe4c676655"
- integrity sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==
-
-"@nodelib/fs.walk@^1.2.3":
- version "1.2.6"
- resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz#cce9396b30aa5afe9e3756608f5831adcb53d063"
- integrity sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==
- dependencies:
- "@nodelib/fs.scandir" "2.1.4"
- fastq "^1.6.0"
-
-"@opentelemetry/api@^0.12.0":
- version "0.12.0"
- resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-0.12.0.tgz#0359c3926e8f16fdcd8c78f196bd1e9fc4e66777"
- integrity sha512-Dn4vU5GlaBrIWzLpsM6xbJwKHdlpwBQ4Bd+cL9ofJP3hKT8jBXpBpribmyaqAzrajzzl2Yt8uTa9rFVLfjDAvw==
- dependencies:
- "@opentelemetry/context-base" "^0.12.0"
-
-"@opentelemetry/context-base@^0.12.0":
- version "0.12.0"
- resolved "https://registry.yarnpkg.com/@opentelemetry/context-base/-/context-base-0.12.0.tgz#4906ae27359d3311e3dea1b63770a16f60848550"
- integrity sha512-UXwSsXo3F3yZ1dIBOG9ID8v2r9e+bqLWoizCtTb8rXtwF+N5TM7hzzvQz72o3nBU+zrI/D5e+OqAYK8ZgDd3DA==
-
-"@opentelemetry/core@^0.12.0":
- version "0.12.0"
- resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-0.12.0.tgz#a888badc9a408fa1f13976a574e69d14be32488e"
- integrity sha512-oLZIkmTNWTJXzo1eA4dGu/S7wOVtylsgnEsCmhSJGhrJVDXm1eW/aGuNs3DVBeuxp0ZvQLAul3/PThsC3YrnzA==
- dependencies:
- "@opentelemetry/api" "^0.12.0"
- "@opentelemetry/context-base" "^0.12.0"
- semver "^7.1.3"
-
-"@opentelemetry/resources@^0.12.0":
- version "0.12.0"
- resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-0.12.0.tgz#5eb287c3032a2bebb2bb9f69b44bd160d2a7d591"
- integrity sha512-8cYvIKB68cyupc7D6SWzkLtt13mbjgxMahL4JKCM6hWPyiGSJlPFEAey4XFXI5LLpPZRYTPHLVoLqI/xwCFZZA==
- dependencies:
- "@opentelemetry/api" "^0.12.0"
- "@opentelemetry/core" "^0.12.0"
-
-"@opentelemetry/semantic-conventions@^0.12.0":
- version "0.12.0"
- resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-0.12.0.tgz#7e392aecdbdbd5d737d3995998b120dc17589ab0"
- integrity sha512-BuCcDW0uLNYYTns0/LwXkJ8lp8aDm7kpS+WunEmPAPRSCe6ciOYRvzn5reqJfX93rf+6A3U2SgrBnCTH+0qoQQ==
-
-"@opentelemetry/tracing@^0.12.0":
- version "0.12.0"
- resolved "https://registry.yarnpkg.com/@opentelemetry/tracing/-/tracing-0.12.0.tgz#769927721d417bfac85eef50c2af068bedce8873"
- integrity sha512-2TUGhTGkhgnxTciHCNAILPSeyXageJewRqfP9wOrx65sKd/jgvNYoY8nYf4EVWVMirDOxKDsmYgUkjdQrwb2dg==
- dependencies:
- "@opentelemetry/api" "^0.12.0"
- "@opentelemetry/context-base" "^0.12.0"
- "@opentelemetry/core" "^0.12.0"
- "@opentelemetry/resources" "^0.12.0"
- "@opentelemetry/semantic-conventions" "^0.12.0"
-
-"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2":
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf"
- integrity sha1-m4sMxmPWaafY9vXQiToU00jzD78=
-
-"@protobufjs/base64@^1.1.2":
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735"
- integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==
-
-"@protobufjs/codegen@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb"
- integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==
-
-"@protobufjs/eventemitter@^1.1.0":
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70"
- integrity sha1-NVy8mLr61ZePntCV85diHx0Ga3A=
-
-"@protobufjs/fetch@^1.1.0":
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45"
- integrity sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=
- dependencies:
- "@protobufjs/aspromise" "^1.1.1"
- "@protobufjs/inquire" "^1.1.0"
-
-"@protobufjs/float@^1.0.2":
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1"
- integrity sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=
-
-"@protobufjs/inquire@^1.1.0":
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089"
- integrity sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=
-
-"@protobufjs/path@^1.1.2":
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d"
- integrity sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=
-
-"@protobufjs/pool@^1.1.0":
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54"
- integrity sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=
-
-"@protobufjs/utf8@^1.1.0":
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
- integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=
-
-"@sendgrid/client@^7.4.2":
- version "7.4.2"
- resolved "https://registry.yarnpkg.com/@sendgrid/client/-/client-7.4.2.tgz#204a9fbb5dc05a721a5d8cd8930f57f9f8e612b1"
- integrity sha512-bu8lLbRD+OV7YsYNemEy8DRoxs8/8u325EXNlQ3VaqhcpbM0eSvdL5e5Wa7VZpbczcNCJmf/sr/uqFmwcO5S+A==
- dependencies:
- "@sendgrid/helpers" "^7.4.2"
- axios "^0.21.1"
-
-"@sendgrid/helpers@^7.4.2":
- version "7.4.2"
- resolved "https://registry.yarnpkg.com/@sendgrid/helpers/-/helpers-7.4.2.tgz#d80f17da439fd241fd69f8a894d93a0fdd19df0f"
- integrity sha512-b/IyBwT4zrOfXA0ISvWZsnhYz+5uAO20n68J8n/6qe5P1E2p0L7kWNTN5LYu0S7snJPUlbEa6FpfrSKzEcP9JA==
- dependencies:
- deepmerge "^4.2.2"
-
-"@sendgrid/mail@^7.4.2":
- version "7.4.2"
- resolved "https://registry.yarnpkg.com/@sendgrid/mail/-/mail-7.4.2.tgz#b2d9f7bccf0f59c814501c0c6db7d6dd963c3fc0"
- integrity sha512-hvIOnm8c3zVyDnJcyBuAeujmpKX56N3D/LpiZrFuLHjAz4iEHrmL2sJ3iU9O6hxcb07gd1CES+z9Fg7FBT26uQ==
- dependencies:
- "@sendgrid/client" "^7.4.2"
- "@sendgrid/helpers" "^7.4.2"
-
-"@sindresorhus/is@^0.14.0":
- version "0.14.0"
- resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea"
- integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==
-
-"@sindresorhus/is@^0.7.0":
- version "0.7.0"
- resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd"
- integrity sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==
-
-"@slack/logger@>=1.0.0 <3.0.0":
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/@slack/logger/-/logger-2.0.0.tgz#6a4e1c755849bc0f66dac08a8be54ce790ec0e6b"
- integrity sha512-OkIJpiU2fz6HOJujhlhfIGrc8hB4ibqtf7nnbJQDerG0BqwZCfmgtK5sWzZ0TkXVRBKD5MpLrTmCYyMxoMCgPw==
- dependencies:
- "@types/node" ">=8.9.0"
-
-"@slack/types@^1.7.0":
- version "1.10.0"
- resolved "https://registry.yarnpkg.com/@slack/types/-/types-1.10.0.tgz#cbf7d83e1027f4cbfd13d6b429f120c7fb09127a"
- integrity sha512-tA7GG7Tj479vojfV3AoxbckalA48aK6giGjNtgH6ihpLwTyHE3fIgRrvt8TWfLwW8X8dyu7vgmAsGLRG7hWWOg==
-
-"@slack/web-api@^6.0.0":
- version "6.0.0"
- resolved "https://registry.yarnpkg.com/@slack/web-api/-/web-api-6.0.0.tgz#14c65ed73c66a187e5f20e12c3898dfd8d5cbf7c"
- integrity sha512-YD1wqWuzrYPf4RQyD7OnYS5lImUmNWn+G5V6Qt0N97fPYxqhT72YJtRdSnsTc3VkH5R5imKOhYxb+wqI9hiHnA==
- dependencies:
- "@slack/logger" ">=1.0.0 <3.0.0"
- "@slack/types" "^1.7.0"
- "@types/is-stream" "^1.1.0"
- "@types/node" ">=12.0.0"
- axios "^0.21.1"
- eventemitter3 "^3.1.0"
- form-data "^2.5.0"
- is-stream "^1.1.0"
- p-queue "^6.6.1"
- p-retry "^4.0.0"
-
-"@szmarczak/http-timer@^1.1.2":
- version "1.1.2"
- 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.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
- integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==
-
-"@types/algoliasearch@^3.34.10":
- version "3.34.11"
- resolved "https://registry.yarnpkg.com/@types/algoliasearch/-/algoliasearch-3.34.11.tgz#a7f3b89a95578be3acd972167bdbadb5dcf71660"
- integrity sha512-FFMbpmXCHcgbypnOUY98SDEoiLc2bXO51gxgX02ypb8srZZnZCPV/8VKknuEtgr1VkgYLrqLi5BoYzZRVni6Fw==
-
-"@types/body-parser@*":
- version "1.19.0"
- resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.0.tgz#0685b3c47eb3006ffed117cdd55164b61f80538f"
- integrity sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==
- dependencies:
- "@types/connect" "*"
- "@types/node" "*"
-
-"@types/connect@*":
- version "3.4.34"
- resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.34.tgz#170a40223a6d666006d93ca128af2beb1d9b1901"
- integrity sha512-ePPA/JuI+X0vb+gSWlPKOY0NdNAie/rPUqX2GUPpbZwiKTkSPhjXWuee47E4MtE54QVzGCQMQkAL6JhV2E1+cQ==
- dependencies:
- "@types/node" "*"
-
-"@types/duplexify@^3.6.0":
- version "3.6.0"
- resolved "https://registry.yarnpkg.com/@types/duplexify/-/duplexify-3.6.0.tgz#dfc82b64bd3a2168f5bd26444af165bf0237dcd8"
- integrity sha512-5zOA53RUlzN74bvrSGwjudssD9F3a797sDZQkiYpUOxW+WHaXTCPz4/d5Dgi6FKnOqZ2CpaTo0DhgIfsXAOE/A==
- dependencies:
- "@types/node" "*"
-
-"@types/express-serve-static-core@*":
- version "4.17.18"
- resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.18.tgz#8371e260f40e0e1ca0c116a9afcd9426fa094c40"
- integrity sha512-m4JTwx5RUBNZvky/JJ8swEJPKFd8si08pPF2PfizYjGZOKr/svUWPcoUmLow6MmPzhasphB7gSTINY67xn3JNA==
- dependencies:
- "@types/node" "*"
- "@types/qs" "*"
- "@types/range-parser" "*"
-
-"@types/express@4.17.3":
- version "4.17.3"
- resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.3.tgz#38e4458ce2067873b09a73908df488870c303bd9"
- integrity sha512-I8cGRJj3pyOLs/HndoP+25vOqhqWkAZsWMEmq1qXy/b/M3ppufecUwaK2/TVDVxcV61/iSdhykUjQQ2DLSrTdg==
- dependencies:
- "@types/body-parser" "*"
- "@types/express-serve-static-core" "*"
- "@types/serve-static" "*"
-
-"@types/glob@^7.1.1":
- version "7.1.3"
- resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.3.tgz#e6ba80f36b7daad2c685acd9266382e68985c183"
- integrity sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==
- dependencies:
- "@types/minimatch" "*"
- "@types/node" "*"
-
-"@types/imagemin-mozjpeg@^8.0.0":
- version "8.0.0"
- resolved "https://registry.yarnpkg.com/@types/imagemin-mozjpeg/-/imagemin-mozjpeg-8.0.0.tgz#6986c34734aa767d83672eeb519379a2d7ec8b16"
- integrity sha512-sR2nEZOrlbgnmVgG+lXetZOvhgtctLe1hBfvySnPnxDd2pOon9mMPq7SHFI89VZT1AXvFgRs8w6X8ik8potpgA==
- dependencies:
- "@types/imagemin" "*"
-
-"@types/imagemin-pngquant@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@types/imagemin-pngquant/-/imagemin-pngquant-7.0.0.tgz#fd074409a369ebc2bf3e6ea77b268a460225b204"
- integrity sha512-9m4EKVKNVy+nkX9Q/jZljGQ32vwYCn25lrbclhOKWrVAHD+MjuJzU/4NB0/loTyZSWyByMJ8sFSGjow66P7nJw==
- dependencies:
- "@types/imagemin" "*"
- "@types/node" "*"
-
-"@types/imagemin@*", "@types/imagemin@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@types/imagemin/-/imagemin-7.0.0.tgz#cb99d719190ebe421015213733d656fac1f8af2e"
- integrity sha512-BiNd5FazD5ZmJUYD9txsbrttL0P0welrb9yAPn6ykKK3kWufwFsxYqw5KdggfZQDjiNYwsBrX+Fwei0Xsw4oAw==
- dependencies:
- "@types/node" "*"
-
-"@types/is-stream@^1.1.0":
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/@types/is-stream/-/is-stream-1.1.0.tgz#b84d7bb207a210f2af9bed431dc0fbe9c4143be1"
- integrity sha512-jkZatu4QVbR60mpIzjINmtS1ZF4a/FqdTUTBeQDVOQ2PYyidtwFKr0B5G6ERukKwliq+7mIXvxyppwzG5EgRYg==
- dependencies:
- "@types/node" "*"
-
-"@types/json2csv@^5.0.1":
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/@types/json2csv/-/json2csv-5.0.1.tgz#576d38515dfedeabf46eb85e790894b8df72ab40"
- integrity sha512-1r5GCTyFtdQ53CRSIctzWZCmtDXvxtzM77SzOqPB4woMeGcc3rhUMzPqEQH3rokG1k/QLzlC5Qe5Ih8NuFN70Q==
- dependencies:
- "@types/node" "*"
-
-"@types/lodash@^4.14.158":
- version "4.14.168"
- resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.168.tgz#fe24632e79b7ade3f132891afff86caa5e5ce008"
- integrity sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q==
-
-"@types/long@^4.0.0", "@types/long@^4.0.1":
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9"
- integrity sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==
-
-"@types/mime@^1":
- version "1.3.2"
- resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a"
- integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==
-
-"@types/minimatch@*", "@types/minimatch@^3.0.3":
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
- integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
-
-"@types/node@*", "@types/node@>=12.0.0", "@types/node@>=8.9.0":
- version "14.14.22"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.22.tgz#0d29f382472c4ccf3bd96ff0ce47daf5b7b84b18"
- integrity sha512-g+f/qj/cNcqKkc3tFqlXOYjrmZA+jNBiDzbP3kH+B+otKFqAdPgVTGP1IeKRdMml/aE69as5S4FqtxAbl+LaMw==
-
-"@types/node@^10.10.0":
- version "10.17.51"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.51.tgz#639538575befbcf3d3861f95c41de8e47124d674"
- integrity sha512-KANw+MkL626tq90l++hGelbl67irOJzGhUJk6a1Bt8QHOeh9tztJx+L0AqttraWKinmZn7Qi5lJZJzx45Gq0dg==
-
-"@types/node@^12.12.47":
- version "12.19.15"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.15.tgz#0de7e978fb43db62da369db18ea088a63673c182"
- integrity sha512-lowukE3GUI+VSYSu6VcBXl14d61Rp5hA1D+61r16qnwC0lYNSqdxcvRh0pswejorHfS+HgwBasM8jLXz0/aOsw==
-
-"@types/node@^13.7.0":
- version "13.13.40"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.40.tgz#f655ef327362cc83912f2e69336ddc62a24a9f88"
- integrity sha512-eKaRo87lu1yAXrzEJl0zcJxfUMDT5/mZalFyOkT44rnQps41eS2pfWzbaulSPpQLFNy29bFqn+Y5lOTL8ATlEQ==
-
-"@types/parse-json@^4.0.0":
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
- integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==
-
-"@types/qs@*":
- version "6.9.5"
- resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.5.tgz#434711bdd49eb5ee69d90c1d67c354a9a8ecb18b"
- integrity sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ==
-
-"@types/range-parser@*":
- version "1.2.3"
- resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c"
- integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==
-
-"@types/retry@^0.12.0":
- version "0.12.0"
- resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d"
- integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==
-
-"@types/serve-static@*":
- version "1.13.9"
- resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.9.tgz#aacf28a85a05ee29a11fb7c3ead935ac56f33e4e"
- integrity sha512-ZFqF6qa48XsPdjXV5Gsz0Zqmux2PerNd3a/ktL45mHpa19cuMi/cL8tcxdAx497yRh+QtYPuofjT9oWw9P7nkA==
- dependencies:
- "@types/mime" "^1"
- "@types/node" "*"
-
-"@types/sharp@^0.25.1":
- version "0.25.1"
- resolved "https://registry.yarnpkg.com/@types/sharp/-/sharp-0.25.1.tgz#9472207f9ef63fd82b134f26e9870cb1ac3290dc"
- integrity sha512-qv9kr1RIad4nZIiIEizjoQyY9VwjwKsl7nJ8LLWHko5SZm/0+/A8ila05YQpKp8BERHxpC+i8Vr8oYyhJtlQBQ==
- dependencies:
- "@types/node" "*"
-
-JSONStream@^1.2.1:
- version "1.3.5"
- resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0"
- integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==
- dependencies:
- jsonparse "^1.2.0"
- through ">=2.2.7 <3"
-
-abbrev@1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
- integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
-
-abort-controller@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
- integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==
- dependencies:
- event-target-shim "^5.0.0"
-
-accepts@~1.3.5, accepts@~1.3.7:
- version "1.3.7"
- resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
- integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==
- dependencies:
- mime-types "~2.1.24"
- negotiator "0.6.2"
-
-agent-base@6, agent-base@^6.0.0:
- version "6.0.2"
- resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
- integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
- dependencies:
- debug "4"
-
-ajv@^6.12.2, ajv@^6.12.3:
- version "6.12.6"
- resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
- integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
- dependencies:
- fast-deep-equal "^3.1.1"
- fast-json-stable-stringify "^2.0.0"
- json-schema-traverse "^0.4.1"
- uri-js "^4.2.2"
-
-algoliasearch@^4.8.6:
- version "4.8.6"
- resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.8.6.tgz#8d6d7d2315bb052705a8ef5c8dbf57a19d357c2b"
- integrity sha512-G8IA3lcgaQB4r9HuQ4G+uSFjjz0Wv2OgEPiQ8emA+G2UUlroOfMl064j1bq/G+QTW0LmTQp9JwrFDRWxFM9J7w==
- dependencies:
- "@algolia/cache-browser-local-storage" "4.8.6"
- "@algolia/cache-common" "4.8.6"
- "@algolia/cache-in-memory" "4.8.6"
- "@algolia/client-account" "4.8.6"
- "@algolia/client-analytics" "4.8.6"
- "@algolia/client-common" "4.8.6"
- "@algolia/client-recommendation" "4.8.6"
- "@algolia/client-search" "4.8.6"
- "@algolia/logger-common" "4.8.6"
- "@algolia/logger-console" "4.8.6"
- "@algolia/requester-browser-xhr" "4.8.6"
- "@algolia/requester-common" "4.8.6"
- "@algolia/requester-node-http" "4.8.6"
- "@algolia/transporter" "4.8.6"
-
-ansi-align@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.0.tgz#b536b371cf687caaef236c18d3e21fe3797467cb"
- integrity sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==
- dependencies:
- string-width "^3.0.0"
-
-ansi-escapes@^3.1.0, ansi-escapes@^3.2.0:
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b"
- integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==
-
-ansi-regex@^2.0.0, ansi-regex@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
- integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8=
-
-ansi-regex@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
- integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
-
-ansi-regex@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
- integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
-
-ansi-regex@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75"
- integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==
-
-ansi-styles@^2.2.1:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
- integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=
-
-ansi-styles@^3.2.1:
- version "3.2.1"
- resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
- integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
- dependencies:
- color-convert "^1.9.0"
-
-ansi-styles@^4.1.0:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
- integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
- dependencies:
- color-convert "^2.0.1"
-
-ansicolors@~0.3.2:
- version "0.3.2"
- resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979"
- integrity sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=
-
-anymatch@~3.1.1:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142"
- integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==
- dependencies:
- normalize-path "^3.0.0"
- picomatch "^2.0.4"
-
-aproba@^1.0.3:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
- integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==
-
-arch@^2.1.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11"
- integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==
-
-archive-type@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/archive-type/-/archive-type-4.0.0.tgz#f92e72233056dfc6969472749c267bdb046b1d70"
- integrity sha1-+S5yIzBW38aWlHJ0nCZ72wRrHXA=
- dependencies:
- file-type "^4.2.0"
-
-archiver-utils@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-2.1.0.tgz#e8a460e94b693c3e3da182a098ca6285ba9249e2"
- integrity sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==
- dependencies:
- glob "^7.1.4"
- graceful-fs "^4.2.0"
- lazystream "^1.0.0"
- lodash.defaults "^4.2.0"
- lodash.difference "^4.5.0"
- lodash.flatten "^4.4.0"
- lodash.isplainobject "^4.0.6"
- lodash.union "^4.6.0"
- normalize-path "^3.0.0"
- readable-stream "^2.0.0"
-
-archiver@^3.0.0:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/archiver/-/archiver-3.1.1.tgz#9db7819d4daf60aec10fe86b16cb9258ced66ea0"
- integrity sha512-5Hxxcig7gw5Jod/8Gq0OneVgLYET+oNHcxgWItq4TbhOzRLKNAFUb9edAftiMKXvXfCB0vbGrJdZDNq0dWMsxg==
- dependencies:
- archiver-utils "^2.1.0"
- async "^2.6.3"
- buffer-crc32 "^0.2.1"
- glob "^7.1.4"
- readable-stream "^3.4.0"
- tar-stream "^2.1.0"
- zip-stream "^2.1.2"
-
-are-we-there-yet@~1.1.2:
- version "1.1.5"
- resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21"
- integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==
- dependencies:
- delegates "^1.0.0"
- readable-stream "^2.0.6"
-
-arg@^4.1.0:
- version "4.1.3"
- 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.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
- integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==
- dependencies:
- sprintf-js "~1.0.2"
-
-array-differ@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-3.0.0.tgz#3cbb3d0f316810eafcc47624734237d6aee4ae6b"
- integrity sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==
-
-array-find-index@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
- integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=
-
-array-flatten@1.1.1, array-flatten@^1.0.0:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
- integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=
-
-array-flatten@3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-3.0.0.tgz#6428ca2ee52c7b823192ec600fa3ed2f157cd541"
- integrity sha512-zPMVc3ZYlGLNk4mpK1NzP2wg0ml9t7fUgDsayR5Y5rSzxQilzR9FGu/EH2jQOcKSAeAfWeylyW8juy3OkWRvNA==
-
-array-union@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
- integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
-
-arrify@^2.0.0, arrify@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa"
- integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==
-
-as-array@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/as-array/-/as-array-1.0.0.tgz#28a6eeeaa5729f1f4eca2047df5e9de1abda0ed1"
- integrity sha1-KKbu6qVynx9OyiBH316d4avaDtE=
- dependencies:
- lodash.isarguments "2.4.x"
- lodash.isobject "^2.4.1"
- lodash.values "^2.4.1"
-
-as-array@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/as-array/-/as-array-2.0.0.tgz#4f04805d87f8fce8e511bc2108f8e5e3a287d547"
- integrity sha1-TwSAXYf4/OjlEbwhCPjl46KH1Uc=
-
-asn1@~0.2.3:
- version "0.2.4"
- resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
- integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
- dependencies:
- safer-buffer "~2.1.0"
-
-assert-plus@1.0.0, assert-plus@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
- integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
-
-ast-types@^0.13.2:
- version "0.13.4"
- resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.4.tgz#ee0d77b343263965ecc3fb62da16e7222b2b6782"
- integrity sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==
- dependencies:
- tslib "^2.0.1"
-
-async-retry@^1.3.1:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/async-retry/-/async-retry-1.3.1.tgz#139f31f8ddce50c0870b0ba558a6079684aaed55"
- integrity sha512-aiieFW/7h3hY0Bq5d+ktDBejxuwR78vRu9hDUdR8rNhSaQ29VzPL4AoIRG7D/c7tdenwOcKvgPM6tIxB3cB6HA==
- dependencies:
- retry "0.12.0"
-
-async@^1.3.0:
- version "1.5.2"
- resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
- integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=
-
-async@^2.6.2, async@^2.6.3:
- version "2.6.3"
- resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff"
- integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==
- dependencies:
- lodash "^4.17.14"
-
-async@^3.1.0:
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/async/-/async-3.2.0.tgz#b3a2685c5ebb641d3de02d161002c60fc9f85720"
- integrity sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==
-
-asynckit@^0.4.0:
- version "0.4.0"
- resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
- integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
-
-aws-sign2@~0.7.0:
- version "0.7.0"
- resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
- integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=
-
-aws4@^1.8.0:
- version "1.11.0"
- resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
- integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
-
-axios@^0.21.1:
- version "0.21.1"
- resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8"
- integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==
- dependencies:
- follow-redirects "^1.10.0"
-
-balanced-match@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
- integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
-
-base64-js@^1.2.3, base64-js@^1.3.0, base64-js@^1.3.1:
- version "1.5.1"
- resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
- integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
-
-basic-auth-connect@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz#fdb0b43962ca7b40456a7c2bb48fe173da2d2122"
- integrity sha1-/bC0OWLKe0BFanwrtI/hc9otISI=
-
-basic-auth@~2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.1.tgz#b998279bf47ce38344b4f3cf916d4679bbf51e3a"
- integrity sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==
- dependencies:
- safe-buffer "5.1.2"
-
-bcrypt-pbkdf@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
- integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
- dependencies:
- tweetnacl "^0.14.3"
-
-big-integer@^1.6.17:
- version "1.6.48"
- resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.48.tgz#8fd88bd1632cba4a1c8c3e3d7159f08bb95b4b9e"
- integrity sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==
-
-bignumber.js@^9.0.0:
- version "9.0.1"
- resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.1.tgz#8d7ba124c882bfd8e43260c67475518d0689e4e5"
- integrity sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==
-
-bin-build@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/bin-build/-/bin-build-3.0.0.tgz#c5780a25a8a9f966d8244217e6c1f5082a143861"
- integrity sha512-jcUOof71/TNAI2uM5uoUaDq2ePcVBQ3R/qhxAz1rX7UfvduAL/RXD3jXzvn8cVcDJdGVkiR1shal3OH0ImpuhA==
- dependencies:
- decompress "^4.0.0"
- download "^6.2.2"
- execa "^0.7.0"
- p-map-series "^1.0.0"
- tempfile "^2.0.0"
-
-bin-check@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/bin-check/-/bin-check-4.1.0.tgz#fc495970bdc88bb1d5a35fc17e65c4a149fc4a49"
- integrity sha512-b6weQyEUKsDGFlACWSIOfveEnImkJyK/FGW6FAG42loyoquvjdtOIqO6yBFzHyqyVVhNgNkQxxx09SFLK28YnA==
- dependencies:
- execa "^0.7.0"
- executable "^4.1.0"
-
-bin-version-check@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/bin-version-check/-/bin-version-check-4.0.0.tgz#7d819c62496991f80d893e6e02a3032361608f71"
- integrity sha512-sR631OrhC+1f8Cvs8WyVWOA33Y8tgwjETNPyyD/myRBXLkfS/vl74FmH/lFcRl9KY3zwGh7jFhvyk9vV3/3ilQ==
- dependencies:
- bin-version "^3.0.0"
- semver "^5.6.0"
- semver-truncate "^1.1.2"
-
-bin-version@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/bin-version/-/bin-version-3.1.0.tgz#5b09eb280752b1bd28f0c9db3f96f2f43b6c0839"
- integrity sha512-Mkfm4iE1VFt4xd4vH+gx+0/71esbfus2LsnCGe8Pi4mndSPyT+NGES/Eg99jx8/lUGWfu3z2yuB/bt5UB+iVbQ==
- dependencies:
- execa "^1.0.0"
- find-versions "^3.0.0"
-
-bin-wrapper@^4.0.0, bin-wrapper@^4.0.1:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/bin-wrapper/-/bin-wrapper-4.1.0.tgz#99348f2cf85031e3ef7efce7e5300aeaae960605"
- integrity sha512-hfRmo7hWIXPkbpi0ZltboCMVrU+0ClXR/JgbCKKjlDjQf6igXa7OwdqNcFWQZPZTgiY7ZpzE3+LjjkLiTN2T7Q==
- dependencies:
- bin-check "^4.1.0"
- bin-version-check "^4.0.0"
- download "^7.1.0"
- import-lazy "^3.1.0"
- os-filter-obj "^2.0.0"
- pify "^4.0.1"
-
-binary-extensions@^2.0.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
- integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
-
-binary@~0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/binary/-/binary-0.3.0.tgz#9f60553bc5ce8c3386f3b553cff47462adecaa79"
- integrity sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=
- dependencies:
- buffers "~0.1.1"
- chainsaw "~0.1.0"
-
-bl@^1.0.0:
- version "1.2.3"
- resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.3.tgz#1e8dd80142eac80d7158c9dccc047fb620e035e7"
- integrity sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==
- dependencies:
- readable-stream "^2.3.5"
- safe-buffer "^5.1.1"
-
-bl@^4.0.3:
- version "4.0.3"
- resolved "https://registry.yarnpkg.com/bl/-/bl-4.0.3.tgz#12d6287adc29080e22a705e5764b2a9522cdc489"
- integrity sha512-fs4G6/Hu4/EE+F75J8DuN/0IpQqNjAdC7aEQv7Qt8MHGUH7Ckv2MwTEEeN9QehD0pfIDkMI1bkHYkKy7xHyKIg==
- dependencies:
- buffer "^5.5.0"
- inherits "^2.0.4"
- readable-stream "^3.4.0"
-
-blakejs@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.1.0.tgz#69df92ef953aa88ca51a32df6ab1c54a155fc7a5"
- integrity sha1-ad+S75U6qIylGjLfarHFShVfx6U=
-
-bluebird@~3.4.1:
- version "3.4.7"
- resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.7.tgz#f72d760be09b7f76d08ed8fae98b289a8d05fab3"
- integrity sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=
-
-body-parser@1.19.0, body-parser@^1.18.3, body-parser@^1.19.0:
- version "1.19.0"
- resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
- integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==
- dependencies:
- bytes "3.1.0"
- content-type "~1.0.4"
- debug "2.6.9"
- depd "~1.1.2"
- http-errors "1.7.2"
- iconv-lite "0.4.24"
- on-finished "~2.3.0"
- qs "6.7.0"
- raw-body "2.4.0"
- type-is "~1.6.17"
-
-boxen@^4.2.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/boxen/-/boxen-4.2.0.tgz#e411b62357d6d6d36587c8ac3d5d974daa070e64"
- integrity sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==
- 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"
-
-brace-expansion@^1.1.7:
- version "1.1.11"
- resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
- integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
- dependencies:
- balanced-match "^1.0.0"
- concat-map "0.0.1"
-
-braces@^3.0.1, braces@~3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
- integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
- dependencies:
- fill-range "^7.0.1"
-
-buffer-alloc-unsafe@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0"
- integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==
-
-buffer-alloc@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec"
- integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==
- dependencies:
- buffer-alloc-unsafe "^1.1.0"
- buffer-fill "^1.0.0"
-
-buffer-crc32@^0.2.1, buffer-crc32@^0.2.13, buffer-crc32@~0.2.3:
- version "0.2.13"
- resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
- integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=
-
-buffer-equal-constant-time@1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
- integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=
-
-buffer-fill@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c"
- integrity sha1-+PeLdniYiO858gXNY39o5wISKyw=
-
-buffer-from@^1.0.0:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
- integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
-
-buffer-indexof-polyfill@~1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz#d2732135c5999c64b277fcf9b1abe3498254729c"
- integrity sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==
-
-buffer@^5.1.0, buffer@^5.2.1, buffer@^5.5.0:
- version "5.7.1"
- 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"
-
-buffers@~0.1.1:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/buffers/-/buffers-0.1.1.tgz#b24579c3bed4d6d396aeee6d9a8ae7f5482ab7bb"
- integrity sha1-skV5w77U1tOWru5tmorn9Ugqt7s=
-
-builtin-modules@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
- integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=
-
-bytes@3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
- integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=
-
-bytes@3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
- integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
-
-cacheable-request@^2.1.1:
- version "2.1.4"
- resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-2.1.4.tgz#0d808801b6342ad33c91df9d0b44dc09b91e5c3d"
- integrity sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=
- dependencies:
- clone-response "1.0.2"
- get-stream "3.0.0"
- http-cache-semantics "3.8.1"
- keyv "3.0.0"
- lowercase-keys "1.0.0"
- normalize-url "2.0.1"
- responselike "1.0.2"
-
-cacheable-request@^6.0.0:
- version "6.1.0"
- 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"
- 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"
-
-call-me-maybe@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b"
- integrity sha1-JtII6onje1y95gJQoV8DHBak1ms=
-
-callsites@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
- integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
-
-camelcase-keys@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7"
- integrity sha1-MIvur/3ygRkFHvodkyITyRuPkuc=
- dependencies:
- camelcase "^2.0.0"
- map-obj "^1.0.0"
-
-camelcase@^2.0.0:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f"
- integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=
-
-camelcase@^5.3.1:
- version "5.3.1"
- resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
- integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
-
-cardinal@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/cardinal/-/cardinal-2.1.1.tgz#7cc1055d822d212954d07b085dea251cc7bc5505"
- integrity sha1-fMEFXYItISlU0HsIXeolHMe8VQU=
- dependencies:
- ansicolors "~0.3.2"
- redeyed "~2.1.0"
-
-caseless@~0.12.0:
- version "0.12.0"
- resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
- integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
-
-caw@^2.0.0, caw@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/caw/-/caw-2.0.1.tgz#6c3ca071fc194720883c2dc5da9b074bfc7e9e95"
- integrity sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==
- dependencies:
- get-proxy "^2.0.0"
- isurl "^1.0.0-alpha5"
- tunnel-agent "^0.6.0"
- url-to-options "^1.0.1"
-
-chainsaw@~0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/chainsaw/-/chainsaw-0.1.0.tgz#5eab50b28afe58074d0d58291388828b5e5fbc98"
- integrity sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=
- dependencies:
- traverse ">=0.3.0 <0.4"
-
-chalk@^1.0.0, chalk@^1.1.3:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
- integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=
- dependencies:
- 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"
-
-chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2:
- version "2.4.2"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
- integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
- dependencies:
- ansi-styles "^3.2.1"
- escape-string-regexp "^1.0.5"
- supports-color "^5.3.0"
-
-chalk@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4"
- integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==
- dependencies:
- ansi-styles "^4.1.0"
- supports-color "^7.1.0"
-
-chalk@^4.0.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a"
- integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==
- dependencies:
- ansi-styles "^4.1.0"
- supports-color "^7.1.0"
-
-chardet@^0.7.0:
- version "0.7.0"
- resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
- integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
-
-chokidar@^3.0.2:
- version "3.5.1"
- resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a"
- integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==
- dependencies:
- anymatch "~3.1.1"
- braces "~3.0.2"
- glob-parent "~5.1.0"
- is-binary-path "~2.1.0"
- is-glob "~4.0.1"
- normalize-path "~3.0.0"
- readdirp "~3.5.0"
- optionalDependencies:
- fsevents "~2.3.1"
-
-chownr@^1.1.1:
- version "1.1.4"
- 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.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.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46"
- integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==
-
-cjson@^0.3.1:
- version "0.3.3"
- resolved "https://registry.yarnpkg.com/cjson/-/cjson-0.3.3.tgz#a92d9c786e5bf9b930806329ee05d5d3261b4afa"
- integrity sha1-qS2ceG5b+bkwgGMp7gXV0yYbSvo=
- dependencies:
- json-parse-helpfulerror "^1.0.3"
-
-cli-boxes@^2.2.0:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f"
- integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==
-
-cli-color@^1.2.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/cli-color/-/cli-color-1.4.0.tgz#7d10738f48526824f8fe7da51857cb0f572fe01f"
- integrity sha512-xu6RvQqqrWEo6MPR1eixqGPywhYBHRs653F9jfXB2Hx4jdM/3WxiNE1vppRmxtMIfl16SFYTpYlrnqH/HsK/2w==
- dependencies:
- ansi-regex "^2.1.1"
- d "1"
- es5-ext "^0.10.46"
- es6-iterator "^2.0.3"
- memoizee "^0.4.14"
- timers-ext "^0.1.5"
-
-cli-cursor@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
- integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=
- dependencies:
- restore-cursor "^2.0.0"
-
-cli-spinners@^2.0.0:
- version "2.5.0"
- resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.5.0.tgz#12763e47251bf951cb75c201dfa58ff1bcb2d047"
- integrity sha512-PC+AmIuK04E6aeSs/pUccSujsTzBhu4HzC2dL+CfJB/Jcc2qTRbEwZQDfIUpt2Xl8BodYBEq8w4fc0kU2I9DjQ==
-
-cli-table@^0.3.1:
- version "0.3.4"
- resolved "https://registry.yarnpkg.com/cli-table/-/cli-table-0.3.4.tgz#5b37fd723751f1a6e9e70d55953a75e16eab958e"
- integrity sha512-1vinpnX/ZERcmE443i3SZTmU5DF0rPO9DrL4I2iVAllhxzCM9SzPlHnz19fsZB78htkKZvYBvj6SZ6vXnaxmTA==
- dependencies:
- chalk "^2.4.1"
- string-width "^4.2.0"
-
-cli-width@^2.0.0:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48"
- integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==
-
-clone-response@1.0.2, clone-response@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b"
- integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=
- dependencies:
- mimic-response "^1.0.0"
-
-clone@^1.0.2:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
- integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4=
-
-code-point-at@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
- integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
-
-color-convert@^1.9.0, color-convert@^1.9.1:
- version "1.9.3"
- resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
- integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
- dependencies:
- color-name "1.1.3"
-
-color-convert@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
- integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
- dependencies:
- color-name "~1.1.4"
-
-color-name@1.1.3:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
- integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
-
-color-name@^1.0.0, color-name@~1.1.4:
- version "1.1.4"
- resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
- integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
-
-color-string@^1.5.2, color-string@^1.5.4:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.6.0.tgz#c3915f61fe267672cb7e1e064c9d692219f6c312"
- integrity sha512-c/hGS+kRWJutUBEngKKmk4iH3sD59MBkoxVapS/0wgpCz2u7XsNloxknyvBhzwEs1IbV36D9PwqLPJ2DTu3vMA==
- dependencies:
- color-name "^1.0.0"
- simple-swizzle "^0.2.2"
-
-color@3.0.x:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/color/-/color-3.0.0.tgz#d920b4328d534a3ac8295d68f7bd4ba6c427be9a"
- integrity sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==
- dependencies:
- color-convert "^1.9.1"
- color-string "^1.5.2"
-
-color@^3.1.2:
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/color/-/color-3.1.3.tgz#ca67fb4e7b97d611dcde39eceed422067d91596e"
- integrity sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ==
- dependencies:
- color-convert "^1.9.1"
- color-string "^1.5.4"
-
-colors@^1.2.1:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
- integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==
-
-colorspace@1.1.x:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.2.tgz#e0128950d082b86a2168580796a0aa5d6c68d8c5"
- integrity sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==
- dependencies:
- color "3.0.x"
- text-hex "1.0.x"
-
-combined-stream@^1.0.6, combined-stream@~1.0.6:
- version "1.0.8"
- 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.12.1, commander@^2.8.1:
- 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==
-
-commander@^4.0.1:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068"
- integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==
-
-compare-semver@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/compare-semver/-/compare-semver-1.1.0.tgz#7c0a79a27bb80b6c6994445f82958259d3d02153"
- integrity sha1-fAp5onu4C2xplERfgpWCWdPQIVM=
- dependencies:
- semver "^5.0.1"
-
-compare-versions@^3.6.0:
- version "3.6.0"
- resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.6.0.tgz#1a5689913685e5a87637b8d3ffca75514ec41d62"
- integrity sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==
-
-compress-commons@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-2.1.1.tgz#9410d9a534cf8435e3fbbb7c6ce48de2dc2f0610"
- integrity sha512-eVw6n7CnEMFzc3duyFVrQEuY1BlHR3rYsSztyG32ibGMW722i3C6IizEGMFmfMU+A+fALvBIwxN3czffTcdA+Q==
- dependencies:
- buffer-crc32 "^0.2.13"
- crc32-stream "^3.0.1"
- normalize-path "^3.0.0"
- readable-stream "^2.3.6"
-
-compressible@^2.0.12, compressible@~2.0.16:
- version "2.0.18"
- resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba"
- integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==
- dependencies:
- mime-db ">= 1.43.0 < 2"
-
-compression@^1.7.0:
- version "1.7.4"
- resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f"
- integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==
- dependencies:
- 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"
-
-concat-map@0.0.1:
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
- integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
-
-config-chain@^1.1.11:
- version "1.1.12"
- resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa"
- integrity sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==
- dependencies:
- ini "^1.3.4"
- proto-list "~1.2.1"
-
-configstore@^5.0.0, configstore@^5.0.1:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96"
- integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==
- 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"
-
-connect@^3.6.2:
- version "3.7.0"
- resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8"
- integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==
- dependencies:
- debug "2.6.9"
- finalhandler "1.1.2"
- parseurl "~1.3.3"
- utils-merge "1.0.1"
-
-console-control-strings@^1.0.0, console-control-strings@~1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
- integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=
-
-console-stream@^0.1.1:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/console-stream/-/console-stream-0.1.1.tgz#a095fe07b20465955f2fafd28b5d72bccd949d44"
- integrity sha1-oJX+B7IEZZVfL6/Si11yvM2UnUQ=
-
-content-disposition@0.5.3, content-disposition@^0.5.2:
- version "0.5.3"
- resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd"
- integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==
- dependencies:
- safe-buffer "5.1.2"
-
-content-type@^1.0.4, content-type@~1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
- integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
-
-cookie-signature@1.0.6:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
- integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw=
-
-cookie@0.4.0:
- version "0.4.0"
- resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba"
- integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==
-
-core-util-is@1.0.2, core-util-is@~1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
- integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
-
-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"
-
-cosmiconfig@^7.0.0:
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.0.tgz#ef9b44d773959cae63ddecd122de23853b60f8d3"
- integrity sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==
- dependencies:
- "@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"
-
-crc32-stream@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-3.0.1.tgz#cae6eeed003b0e44d739d279de5ae63b171b4e85"
- integrity sha512-mctvpXlbzsvK+6z8kJwSJ5crm7yBwrQMTybJzMw1O4lLGJqjlDCXY2Zw7KheiA6XBEcBmfLx1D88mjRGVJtY9w==
- dependencies:
- crc "^3.4.4"
- readable-stream "^3.4.0"
-
-crc@^3.4.4:
- version "3.8.0"
- resolved "https://registry.yarnpkg.com/crc/-/crc-3.8.0.tgz#ad60269c2c856f8c299e2c4cc0de4556914056c6"
- integrity sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==
- dependencies:
- buffer "^5.1.0"
-
-cross-env@^5.1.3:
- version "5.2.1"
- resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-5.2.1.tgz#b2c76c1ca7add66dc874d11798466094f551b34d"
- integrity sha512-1yHhtcfAd1r4nwQgknowuUNfIT9E8dOMMspC36g45dN+iD1blloi7xp8X/xAIDnjHWyt1uQ8PHk2fkNaym7soQ==
- dependencies:
- cross-spawn "^6.0.5"
-
-cross-spawn@^5.0.1:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
- integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=
- dependencies:
- lru-cache "^4.0.1"
- shebang-command "^1.2.0"
- which "^1.2.9"
-
-cross-spawn@^6.0.0, cross-spawn@^6.0.5:
- version "6.0.5"
- resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
- integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
- dependencies:
- nice-try "^1.0.4"
- path-key "^2.0.1"
- semver "^5.5.0"
- shebang-command "^1.2.0"
- which "^1.2.9"
-
-cross-spawn@^7.0.0, cross-spawn@^7.0.1:
- version "7.0.3"
- resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
- integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
- dependencies:
- path-key "^3.1.0"
- shebang-command "^2.0.0"
- which "^2.0.1"
-
-crypto-random-string@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5"
- integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==
-
-csv-streamify@^3.0.4:
- version "3.0.4"
- resolved "https://registry.yarnpkg.com/csv-streamify/-/csv-streamify-3.0.4.tgz#4cb614c57e3f299cca17b63fdcb4ad167777f47a"
- integrity sha1-TLYUxX4/KZzKF7Y/3LStFnd39Ho=
- dependencies:
- through2 "2.0.1"
-
-currently-unhandled@^0.4.1:
- version "0.4.1"
- resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"
- integrity sha1-mI3zP+qxke95mmE2nddsF635V+o=
- dependencies:
- array-find-index "^1.0.1"
-
-d@1, d@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a"
- integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==
- dependencies:
- es5-ext "^0.10.50"
- type "^1.0.1"
-
-dashdash@^1.12.0:
- version "1.14.1"
- resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
- integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=
- dependencies:
- assert-plus "^1.0.0"
-
-data-uri-to-buffer@3:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz#594b8973938c5bc2c33046535785341abc4f3636"
- integrity sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==
-
-date-and-time@^0.14.2:
- version "0.14.2"
- resolved "https://registry.yarnpkg.com/date-and-time/-/date-and-time-0.14.2.tgz#a4266c3dead460f6c231fe9674e585908dac354e"
- integrity sha512-EFTCh9zRSEpGPmJaexg7HTuzZHh6cnJj1ui7IGCFNXzd2QdpsNh05Db5TF3xzJm30YN+A8/6xHSuRcQqoc3kFA==
-
-debug@2.6.9:
- version "2.6.9"
- resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
- integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
- dependencies:
- ms "2.0.0"
-
-debug@4, debug@4.3.1, debug@^4.1.1:
- version "4.3.1"
- resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee"
- integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==
- dependencies:
- ms "2.1.2"
-
-debug@^3.1.1:
- 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.1.2:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
- integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
-
-decode-uri-component@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
- integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
-
-decompress-response@^3.2.0, decompress-response@^3.3.0:
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3"
- integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=
- dependencies:
- mimic-response "^1.0.0"
-
-decompress-response@^4.2.0:
- version "4.2.1"
- resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-4.2.1.tgz#414023cc7a302da25ce2ec82d0d5238ccafd8986"
- integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==
- dependencies:
- mimic-response "^2.0.0"
-
-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 "^3.1.0"
-
-decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1"
- integrity sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==
- dependencies:
- file-type "^5.2.0"
- is-stream "^1.1.0"
- tar-stream "^1.5.2"
-
-decompress-tarbz2@^4.0.0:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b"
- integrity sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==
- dependencies:
- decompress-tar "^4.1.0"
- file-type "^6.1.0"
- is-stream "^1.1.0"
- seek-bzip "^1.0.5"
- unbzip2-stream "^1.0.9"
-
-decompress-targz@^4.0.0:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee"
- integrity sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==
- dependencies:
- decompress-tar "^4.1.1"
- file-type "^5.2.0"
- is-stream "^1.1.0"
-
-decompress-unzip@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69"
- integrity sha1-3qrM39FK6vhVePczroIQ+bSEj2k=
- dependencies:
- file-type "^3.8.0"
- get-stream "^2.2.0"
- pify "^2.3.0"
- yauzl "^2.4.2"
-
-decompress@^4.0.0, decompress@^4.2.0:
- version "4.2.1"
- resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.1.tgz#007f55cc6a62c055afa37c07eb6a4ee1b773f118"
- integrity sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==
- dependencies:
- decompress-tar "^4.0.0"
- decompress-tarbz2 "^4.0.0"
- decompress-targz "^4.0.0"
- decompress-unzip "^4.0.1"
- graceful-fs "^4.1.10"
- make-dir "^1.0.0"
- pify "^2.3.0"
- strip-dirs "^2.0.0"
-
-deep-extend@^0.6.0:
- version "0.6.0"
- resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
- integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
-
-deep-freeze@0.0.1:
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/deep-freeze/-/deep-freeze-0.0.1.tgz#3a0b0005de18672819dfd38cd31f91179c893e84"
- integrity sha1-OgsABd4YZygZ39OM0x+RF5yJPoQ=
-
-deep-is@^0.1.3, deep-is@~0.1.3:
- version "0.1.3"
- resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
- integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
-
-deepmerge@^4.2.2:
- version "4.2.2"
- 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.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d"
- integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=
- dependencies:
- clone "^1.0.2"
-
-defer-to-connect@^1.0.1:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591"
- integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==
-
-degenerator@^2.2.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/degenerator/-/degenerator-2.2.0.tgz#49e98c11fa0293c5b26edfbb52f15729afcdb254"
- integrity sha512-aiQcQowF01RxFI4ZLFMpzyotbQonhNpBao6dkI8JPk5a+hmSjR5ErHp2CQySmQe8os3VBqLCIh87nDBgZXvsmg==
- dependencies:
- ast-types "^0.13.2"
- escodegen "^1.8.1"
- esprima "^4.0.0"
-
-delayed-stream@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
- integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
-
-delegates@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
- integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=
-
-depd@~1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
- integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
-
-depd@~2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
- integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
-
-destroy@^1.0.4, destroy@~1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
- integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
-
-detect-libc@^1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
- integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=
-
-dicer@^0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/dicer/-/dicer-0.3.0.tgz#eacd98b3bfbf92e8ab5c2fdb71aaac44bb06b872"
- integrity sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA==
- dependencies:
- streamsearch "0.1.2"
-
-diff@^4.0.1:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
- integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
-
-dir-glob@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
- integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==
- dependencies:
- path-type "^4.0.0"
-
-dot-prop@^5.2.0:
- version "5.3.0"
- resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88"
- integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==
- dependencies:
- is-obj "^2.0.0"
-
-dotenv@^6.1.0:
- version "6.2.0"
- resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-6.2.0.tgz#941c0410535d942c8becf28d3f357dbd9d476064"
- integrity sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w==
-
-download@^6.2.2:
- version "6.2.5"
- resolved "https://registry.yarnpkg.com/download/-/download-6.2.5.tgz#acd6a542e4cd0bb42ca70cfc98c9e43b07039714"
- integrity sha512-DpO9K1sXAST8Cpzb7kmEhogJxymyVUd5qz/vCOSyvwtp2Klj2XcDt5YUuasgxka44SxF0q5RriKIwJmQHG2AuA==
- dependencies:
- caw "^2.0.0"
- content-disposition "^0.5.2"
- decompress "^4.0.0"
- ext-name "^5.0.0"
- file-type "5.2.0"
- filenamify "^2.0.0"
- get-stream "^3.0.0"
- got "^7.0.0"
- make-dir "^1.0.0"
- p-event "^1.0.0"
- pify "^3.0.0"
-
-download@^7.1.0:
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/download/-/download-7.1.0.tgz#9059aa9d70b503ee76a132897be6dec8e5587233"
- integrity sha512-xqnBTVd/E+GxJVrX5/eUJiLYjCGPwMpdL+jGhGU57BvtcA7wwhtHVbXBeUk51kOpW3S7Jn3BQbN9Q1R1Km2qDQ==
- dependencies:
- archive-type "^4.0.0"
- caw "^2.0.1"
- content-disposition "^0.5.2"
- decompress "^4.2.0"
- ext-name "^5.0.0"
- file-type "^8.1.0"
- filenamify "^2.0.0"
- get-stream "^3.0.0"
- got "^8.3.1"
- make-dir "^1.2.0"
- p-event "^2.1.0"
- pify "^3.0.0"
-
-duplexer2@~0.1.4:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1"
- integrity sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=
- dependencies:
- readable-stream "^2.0.2"
-
-duplexer3@^0.1.4:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
- integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=
-
-duplexify@^4.0.0, duplexify@^4.1.1:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.1.tgz#7027dc374f157b122a8ae08c2d3ea4d2d953aa61"
- integrity sha512-DY3xVEmVHTv1wSzKNbwoU6nVjzI369Y6sPoqfYr0/xlx3IdX2n94xIszTcjPO8W8ZIv0Wb0PXNcjuZyT4wiICA==
- dependencies:
- end-of-stream "^1.4.1"
- inherits "^2.0.3"
- readable-stream "^3.1.1"
- stream-shift "^1.0.0"
-
-ecc-jsbn@~0.1.1:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
- integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=
- dependencies:
- jsbn "~0.1.0"
- safer-buffer "^2.1.0"
-
-ecdsa-sig-formatter@1.0.11, ecdsa-sig-formatter@^1.0.11:
- version "1.0.11"
- 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"
-
-ee-first@1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
- integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
-
-emoji-regex@^7.0.1:
- version "7.0.3"
- resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
- integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==
-
-emoji-regex@^8.0.0:
- version "8.0.0"
- resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
- integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
-
-enabled@2.0.x:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2"
- integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==
-
-encodeurl@~1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
- integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
-
-end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1:
- version "1.4.4"
- resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
- integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
- dependencies:
- once "^1.4.0"
-
-ent@^2.2.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d"
- integrity sha1-6WQhkyWiHQX0RGai9obtbOX13R0=
-
-env-paths@^2.2.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.0.tgz#cdca557dc009152917d6166e2febe1f039685e43"
- integrity sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==
-
-error-ex@^1.2.0, error-ex@^1.3.1:
- version "1.3.2"
- resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
- integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
- dependencies:
- is-arrayish "^0.2.1"
-
-es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@^0.10.53, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46:
- version "0.10.53"
- resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1"
- integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==
- dependencies:
- es6-iterator "~2.0.3"
- es6-symbol "~3.1.3"
- next-tick "~1.0.0"
-
-es6-iterator@^2.0.3, es6-iterator@~2.0.3:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7"
- integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c=
- dependencies:
- d "1"
- es5-ext "^0.10.35"
- es6-symbol "^3.1.1"
-
-es6-symbol@^3.1.1, es6-symbol@~3.1.3:
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18"
- integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==
- dependencies:
- d "^1.0.1"
- ext "^1.1.2"
-
-es6-weak-map@^2.0.3:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.3.tgz#b6da1f16cc2cc0d9be43e6bdbfc5e7dfcdf31d53"
- integrity sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==
- dependencies:
- d "1"
- es5-ext "^0.10.46"
- es6-iterator "^2.0.3"
- es6-symbol "^3.1.1"
-
-escape-goat@^2.0.0:
- version "2.1.1"
- 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.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
- integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=
-
-escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
- integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
-
-escodegen@^1.8.1:
- version "1.14.3"
- resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503"
- integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==
- dependencies:
- esprima "^4.0.1"
- estraverse "^4.2.0"
- esutils "^2.0.2"
- optionator "^0.8.1"
- optionalDependencies:
- source-map "~0.6.1"
-
-esprima@^4.0.0, esprima@^4.0.1, esprima@~4.0.0:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
- integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
-
-estraverse@^4.2.0:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
- integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
-
-esutils@^2.0.2:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
- integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
-
-etag@~1.8.1:
- version "1.8.1"
- resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
- integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
-
-event-emitter@^0.3.5:
- version "0.3.5"
- resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39"
- integrity sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=
- dependencies:
- d "1"
- es5-ext "~0.10.14"
-
-event-target-shim@^5.0.0:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789"
- integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==
-
-eventemitter3@^3.1.0:
- version "3.1.2"
- resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7"
- integrity sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==
-
-eventemitter3@^4.0.4:
- version "4.0.7"
- resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
- integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==
-
-events-listener@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/events-listener/-/events-listener-1.1.0.tgz#dd49b4628480eba58fde31b870ee346b3990b349"
- integrity sha512-Kd3EgYfODHueq6GzVfs/VUolh2EgJsS8hkO3KpnDrxVjU3eq63eXM2ujXkhPP+OkeUOhL8CxdfZbQXzryb5C4g==
-
-execa@^0.7.0:
- version "0.7.0"
- resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777"
- integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=
- dependencies:
- cross-spawn "^5.0.1"
- get-stream "^3.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"
-
-execa@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8"
- integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==
- 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"
-
-execa@^4.0.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a"
- integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==
- 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"
-
-executable@^4.1.0:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/executable/-/executable-4.1.1.tgz#41532bff361d3e57af4d763b70582db18f5d133c"
- integrity sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==
- dependencies:
- pify "^2.2.0"
-
-exegesis-express@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/exegesis-express/-/exegesis-express-2.0.0.tgz#e33b2ed35e52162ce78613868a771ee4cb5636a7"
- integrity sha512-NKvKBsBa2OvU+1BFpWbz3PzoRMhA9q7/wU2oMmQ9X8lPy/FRatADvhlkGO1zYOMgeo35k1ZLO9ZV0uIs9pPnXg==
- dependencies:
- exegesis "^2.0.0"
-
-exegesis@^2.0.0:
- version "2.5.6"
- resolved "https://registry.yarnpkg.com/exegesis/-/exegesis-2.5.6.tgz#2a5f198a857b6d820f6bfa0ad41fe29e6fe97446"
- integrity sha512-e+YkH/zZTN2njiwrV8tY6tHGDsFu3LyR/YbrqdWvDZaAJ5YGWaBYyd3oX/Y26iGqQc+7jLEKLDTv2UPzjAYL8w==
- dependencies:
- "@apidevtools/json-schema-ref-parser" "^9.0.3"
- ajv "^6.12.2"
- body-parser "^1.18.3"
- content-type "^1.0.4"
- deep-freeze "0.0.1"
- events-listener "^1.1.0"
- glob "^7.1.3"
- json-ptr "^1.3.1"
- json-schema-traverse "^0.4.1"
- lodash "^4.17.11"
- openapi3-ts "^1.2.0"
- promise-breaker "^5.0.0"
- pump "^3.0.0"
- qs "^6.6.0"
- raw-body "^2.3.3"
- semver "^7.0.0"
-
-exit-code@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/exit-code/-/exit-code-1.0.2.tgz#ce165811c9f117af6a5f882940b96ae7f9aecc34"
- integrity sha1-zhZYEcnxF69qX4gpQLlq5/muzDQ=
-
-expand-template@^2.0.3:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c"
- integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==
-
-express@^4.16.4, express@^4.17.1:
- version "4.17.1"
- resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134"
- integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==
- dependencies:
- accepts "~1.3.7"
- array-flatten "1.1.1"
- body-parser "1.19.0"
- content-disposition "0.5.3"
- content-type "~1.0.4"
- cookie "0.4.0"
- cookie-signature "1.0.6"
- debug "2.6.9"
- depd "~1.1.2"
- encodeurl "~1.0.2"
- escape-html "~1.0.3"
- etag "~1.8.1"
- finalhandler "~1.1.2"
- fresh "0.5.2"
- merge-descriptors "1.0.1"
- methods "~1.1.2"
- on-finished "~2.3.0"
- parseurl "~1.3.3"
- path-to-regexp "0.1.7"
- proxy-addr "~2.0.5"
- qs "6.7.0"
- range-parser "~1.2.1"
- safe-buffer "5.1.2"
- send "0.17.1"
- serve-static "1.14.1"
- setprototypeof "1.1.1"
- statuses "~1.5.0"
- type-is "~1.6.18"
- utils-merge "1.0.1"
- vary "~1.1.2"
-
-ext-list@^2.0.0:
- version "2.2.2"
- resolved "https://registry.yarnpkg.com/ext-list/-/ext-list-2.2.2.tgz#0b98e64ed82f5acf0f2931babf69212ef52ddd37"
- integrity sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==
- dependencies:
- mime-db "^1.28.0"
-
-ext-name@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/ext-name/-/ext-name-5.0.0.tgz#70781981d183ee15d13993c8822045c506c8f0a6"
- integrity sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==
- dependencies:
- ext-list "^2.0.0"
- sort-keys-length "^1.0.0"
-
-ext@^1.1.2:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/ext/-/ext-1.4.0.tgz#89ae7a07158f79d35517882904324077e4379244"
- integrity sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==
- dependencies:
- type "^2.0.0"
-
-extend@^3.0.2, extend@~3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
- integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
-
-external-editor@^3.0.3:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495"
- integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==
- dependencies:
- chardet "^0.7.0"
- iconv-lite "^0.4.24"
- tmp "^0.0.33"
-
-extsprintf@1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
- integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=
-
-extsprintf@^1.2.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
- integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
-
-fast-deep-equal@^3.1.1:
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
- integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
-
-fast-glob@^3.0.3:
- version "3.2.5"
- resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.5.tgz#7939af2a656de79a4f1901903ee8adcaa7cb9661"
- integrity sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==
- dependencies:
- "@nodelib/fs.stat" "^2.0.2"
- "@nodelib/fs.walk" "^1.2.3"
- glob-parent "^5.1.0"
- merge2 "^1.3.0"
- micromatch "^4.0.2"
- picomatch "^2.2.1"
-
-fast-json-stable-stringify@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
- integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
-
-fast-levenshtein@~2.0.6:
- version "2.0.6"
- resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
- integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
-
-fast-safe-stringify@^2.0.4:
- version "2.0.7"
- resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz#124aa885899261f68aedb42a7c080de9da608743"
- integrity sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==
-
-fast-text-encoding@^1.0.0, fast-text-encoding@^1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz#ec02ac8e01ab8a319af182dae2681213cfe9ce53"
- integrity sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig==
-
-fast-url-parser@^1.1.3:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d"
- integrity sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0=
- dependencies:
- punycode "^1.3.2"
-
-fastq@^1.6.0:
- version "1.10.1"
- resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.10.1.tgz#8b8f2ac8bf3632d67afcd65dac248d5fdc45385e"
- integrity sha512-AWuv6Ery3pM+dY7LYS8YIaCiQvUaos9OB1RyNgaOWnaX+Tik7Onvcsf8x8c+YtDeT0maYLniBip2hox5KtEXXA==
- dependencies:
- reusify "^1.0.4"
-
-faye-websocket@0.11.3:
- version "0.11.3"
- resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.3.tgz#5c0e9a8968e8912c286639fde977a8b209f2508e"
- integrity sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==
- dependencies:
- websocket-driver ">=0.5.1"
-
-fd-slicer@~1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e"
- integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=
- dependencies:
- pend "~1.2.0"
-
-fecha@^4.2.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.0.tgz#3ffb6395453e3f3efff850404f0a59b6747f5f41"
- integrity sha512-aN3pcx/DSmtyoovUudctc8+6Hl4T+hI9GBBHLjA76jdZl7+b1sgh5g4k+u/GL3dTy1/pnYzKp69FpJ0OicE3Wg==
-
-figures@^1.3.5:
- version "1.7.0"
- resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e"
- integrity sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=
- dependencies:
- escape-string-regexp "^1.0.5"
- object-assign "^4.1.0"
-
-figures@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962"
- integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=
- dependencies:
- escape-string-regexp "^1.0.5"
-
-file-type@5.2.0, file-type@^5.2.0:
- version "5.2.0"
- resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6"
- integrity sha1-LdvqfHP/42No365J3DOMBYwritY=
-
-file-type@^12.0.0:
- version "12.4.2"
- resolved "https://registry.yarnpkg.com/file-type/-/file-type-12.4.2.tgz#a344ea5664a1d01447ee7fb1b635f72feb6169d9"
- integrity sha512-UssQP5ZgIOKelfsaB5CuGAL+Y+q7EmONuiwF3N5HAH0t27rvrttgi6Ra9k/+DVaY9UF6+ybxu5pOXLUdA8N7Vg==
-
-file-type@^3.8.0:
- version "3.9.0"
- resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9"
- integrity sha1-JXoHg4TR24CHvESdEH1SpSZyuek=
-
-file-type@^4.2.0:
- version "4.4.0"
- resolved "https://registry.yarnpkg.com/file-type/-/file-type-4.4.0.tgz#1b600e5fca1fbdc6e80c0a70c71c8dba5f7906c5"
- integrity sha1-G2AOX8ofvcboDApwxxyNul95BsU=
-
-file-type@^6.1.0:
- version "6.2.0"
- resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919"
- integrity sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==
-
-file-type@^8.1.0:
- version "8.1.0"
- resolved "https://registry.yarnpkg.com/file-type/-/file-type-8.1.0.tgz#244f3b7ef641bbe0cca196c7276e4b332399f68c"
- integrity sha512-qyQ0pzAy78gVoJsmYeNgl8uH8yKhr1lVhW7JbzJmnlRi0I4R2eEDEJZVKG8agpDnLpacwNbDhLNG/LMdxHD2YQ==
-
-file-uri-to-path@2:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-2.0.0.tgz#7b415aeba227d575851e0a5b0c640d7656403fba"
- integrity sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg==
-
-filename-reserved-regex@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz#abf73dfab735d045440abfea2d91f389ebbfa229"
- integrity sha1-q/c9+rc10EVECr/qLZHzieu/oik=
-
-filenamify@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/filenamify/-/filenamify-2.1.0.tgz#88faf495fb1b47abfd612300002a16228c677ee9"
- integrity sha512-ICw7NTT6RsDp2rnYKVd8Fu4cr6ITzGy3+u4vUujPkabyaz+03F24NWEX7fs5fp+kBonlaqPH8fAO2NM+SXt/JA==
- dependencies:
- filename-reserved-regex "^2.0.0"
- strip-outer "^1.0.0"
- trim-repeated "^1.0.0"
-
-filesize@^3.1.3:
- version "3.6.1"
- resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317"
- integrity sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==
-
-fill-range@^7.0.1:
- version "7.0.1"
- 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"
-
-finalhandler@1.1.2, finalhandler@~1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d"
- integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==
- dependencies:
- debug "2.6.9"
- encodeurl "~1.0.2"
- escape-html "~1.0.3"
- on-finished "~2.3.0"
- parseurl "~1.3.3"
- statuses "~1.5.0"
- unpipe "~1.0.0"
-
-find-up@^1.0.0:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
- integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=
- dependencies:
- path-exists "^2.0.0"
- pinkie-promise "^2.0.0"
-
-find-up@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
- integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
- dependencies:
- locate-path "^5.0.0"
- path-exists "^4.0.0"
-
-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"
-
-find-versions@^3.0.0:
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/find-versions/-/find-versions-3.2.0.tgz#10297f98030a786829681690545ef659ed1d254e"
- integrity sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==
- dependencies:
- semver-regex "^2.0.0"
-
-find-versions@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/find-versions/-/find-versions-4.0.0.tgz#3c57e573bf97769b8cb8df16934b627915da4965"
- integrity sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==
- dependencies:
- semver-regex "^3.1.2"
-
-firebase-admin@^9.4.2:
- version "9.4.2"
- resolved "https://registry.yarnpkg.com/firebase-admin/-/firebase-admin-9.4.2.tgz#190d5d7ca5e3f251d99503feb6e05e7ab1623851"
- integrity sha512-mRnBJbW6BAz6DJkZ0GOUTkmnmCrwVzMreMc6O+RXWukFydOzi5Xr6TKSiPKxoOQw41r9IluP2AZ3Qzvlx2SR+g==
- dependencies:
- "@firebase/database" "^0.8.1"
- "@firebase/database-types" "^0.6.1"
- "@types/node" "^10.10.0"
- dicer "^0.3.0"
- jsonwebtoken "^8.5.1"
- node-forge "^0.10.0"
- optionalDependencies:
- "@google-cloud/firestore" "^4.5.0"
- "@google-cloud/storage" "^5.3.0"
-
-firebase-functions@^3.13.1:
- version "3.13.1"
- resolved "https://registry.yarnpkg.com/firebase-functions/-/firebase-functions-3.13.1.tgz#a34e61ab328903fe88a9532d267f031d9a0d9e23"
- integrity sha512-tmYHN9OWWIij/8xO72AD2sKHm9T8pdLPYXy5RWk9VidP8+LDOUZ68vq1g1WKeSkRR7WyVYQ3scU2QoMDfe9T8g==
- dependencies:
- "@types/express" "4.17.3"
- cors "^2.8.5"
- express "^4.17.1"
- lodash "^4.17.14"
-
-firebase-tools@^9.2.2:
- version "9.3.0"
- resolved "https://registry.yarnpkg.com/firebase-tools/-/firebase-tools-9.3.0.tgz#8bb8dec8218a0cd8db8694ebd5f5a6c9bf495ce7"
- integrity sha512-tLg1GKpf8Jxlgqq3JttWTOHsOKIyNpro0Ic5sOabmxd1XSeXdK0XW3r3INASoSpy1SYPQn5EEyR1Vs/a0gCu2w==
- dependencies:
- "@google-cloud/pubsub" "^2.7.0"
- JSONStream "^1.2.1"
- abort-controller "^3.0.0"
- archiver "^3.0.0"
- body-parser "^1.19.0"
- chokidar "^3.0.2"
- cjson "^0.3.1"
- cli-color "^1.2.0"
- cli-table "^0.3.1"
- commander "^4.0.1"
- configstore "^5.0.1"
- cross-env "^5.1.3"
- cross-spawn "^7.0.1"
- csv-streamify "^3.0.4"
- dotenv "^6.1.0"
- exegesis-express "^2.0.0"
- exit-code "^1.0.2"
- express "^4.16.4"
- filesize "^3.1.3"
- fs-extra "^0.23.1"
- glob "^7.1.2"
- google-auth-library "^6.1.3"
- inquirer "~6.3.1"
- js-yaml "^3.13.1"
- jsonschema "^1.0.2"
- jsonwebtoken "^8.2.1"
- leven "^3.1.0"
- lodash "^4.17.19"
- marked "^0.7.0"
- marked-terminal "^3.3.0"
- minimatch "^3.0.4"
- morgan "^1.10.0"
- node-fetch "^2.6.1"
- open "^6.3.0"
- ora "^3.4.0"
- plist "^3.0.1"
- portfinder "^1.0.23"
- progress "^2.0.3"
- proxy-agent "^4.0.0"
- request "^2.87.0"
- rimraf "^3.0.0"
- semver "^5.7.1"
- superstatic "^7.1.0"
- tar "^4.3.0"
- tcp-port-used "^1.0.1"
- tmp "0.0.33"
- triple-beam "^1.3.0"
- tweetsodium "0.0.5"
- universal-analytics "^0.4.16"
- unzipper "^0.10.10"
- update-notifier "^4.1.0"
- uuid "^3.0.0"
- winston "^3.0.0"
- ws "^7.2.3"
-
-flat-arguments@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/flat-arguments/-/flat-arguments-1.0.2.tgz#9baa780adf0501f282d726c9c6a038dba44ea76f"
- integrity sha1-m6p4Ct8FAfKC1ybJxqA426ROp28=
- dependencies:
- array-flatten "^1.0.0"
- as-array "^1.0.0"
- lodash.isarguments "^3.0.0"
- lodash.isobject "^3.0.0"
-
-fn.name@1.x.x:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc"
- integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==
-
-follow-redirects@^1.10.0:
- version "1.13.2"
- resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.2.tgz#dd73c8effc12728ba5cf4259d760ea5fb83e3147"
- integrity sha512-6mPTgLxYm3r6Bkkg0vNM0HTjfGrOEtsfbhagQvbxDEsEkpNhw582upBaoRZylzen6krEmxXJgt9Ju6HiI4O7BA==
-
-forever-agent@~0.6.1:
- version "0.6.1"
- resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
- integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
-
-form-data@^2.5.0:
- version "2.5.1"
- resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4"
- integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==
- dependencies:
- asynckit "^0.4.0"
- combined-stream "^1.0.6"
- mime-types "^2.1.12"
-
-form-data@~2.3.2:
- version "2.3.3"
- resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
- integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==
- dependencies:
- asynckit "^0.4.0"
- combined-stream "^1.0.6"
- mime-types "^2.1.12"
-
-forwarded@~0.1.2:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
- integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=
-
-fresh@0.5.2:
- version "0.5.2"
- resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
- integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=
-
-from2@^2.1.1:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af"
- integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=
- dependencies:
- inherits "^2.0.1"
- readable-stream "^2.0.0"
-
-fs-constants@^1.0.0:
- version "1.0.0"
- 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@^0.23.1:
- version "0.23.1"
- resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.23.1.tgz#6611dba6adf2ab8dc9c69fab37cddf8818157e3d"
- integrity sha1-ZhHbpq3yq43Jxp+rN83fiBgVfj0=
- dependencies:
- graceful-fs "^4.1.2"
- jsonfile "^2.1.0"
- path-is-absolute "^1.0.0"
- rimraf "^2.2.8"
-
-fs-extra@^8.1.0:
- version "8.1.0"
- resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0"
- integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==
- dependencies:
- graceful-fs "^4.2.0"
- jsonfile "^4.0.0"
- universalify "^0.1.0"
-
-fs-minipass@^1.2.5:
- version "1.2.7"
- resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7"
- integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==
- dependencies:
- minipass "^2.6.0"
-
-fs-minipass@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
- integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==
- dependencies:
- minipass "^3.0.0"
-
-fs.realpath@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
- integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
-
-fsevents@~2.3.1:
- version "2.3.1"
- resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.1.tgz#b209ab14c61012636c8863507edf7fb68cc54e9f"
- integrity sha512-YR47Eg4hChJGAB1O3yEAOkGO+rlzutoICGqGo9EZ4lKWokzZRSyIW1QmTzqjtw8MJdj9srP869CuWw/hyzSiBw==
-
-fstream@^1.0.12:
- version "1.0.12"
- resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045"
- integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==
- dependencies:
- graceful-fs "^4.1.2"
- inherits "~2.0.0"
- mkdirp ">=0.5 0"
- rimraf "2"
-
-ftp@^0.3.10:
- version "0.3.10"
- resolved "https://registry.yarnpkg.com/ftp/-/ftp-0.3.10.tgz#9197d861ad8142f3e63d5a83bfe4c59f7330885d"
- integrity sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=
- dependencies:
- readable-stream "1.1.x"
- xregexp "2.0.0"
-
-function-bind@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
- integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
-
-functional-red-black-tree@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
- integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=
-
-gauge@~2.7.3:
- version "2.7.4"
- resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
- 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"
-
-gaxios@^4.0.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/gaxios/-/gaxios-4.1.0.tgz#e8ad466db5a4383c70b9d63bfd14dfaa87eb0099"
- integrity sha512-vb0to8xzGnA2qcgywAjtshOKKVDf2eQhJoiL6fHhgW5tVN7wNk7egnYIO9zotfn3lQ3De1VPdf7V5/BWfCtCmg==
- dependencies:
- abort-controller "^3.0.0"
- extend "^3.0.2"
- https-proxy-agent "^5.0.0"
- is-stream "^2.0.0"
- node-fetch "^2.3.0"
-
-gcp-metadata@^4.2.0:
- version "4.2.1"
- resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-4.2.1.tgz#31849fbcf9025ef34c2297c32a89a1e7e9f2cd62"
- integrity sha512-tSk+REe5iq/N+K+SK1XjZJUrFPuDqGZVzCy2vocIHIGmPlTGsa8owXMJwGkrXr73NO0AzhPW4MF2DEHz7P2AVw==
- dependencies:
- gaxios "^4.0.0"
- json-bigint "^1.0.0"
-
-gcs-resumable-upload@^3.1.0:
- version "3.1.2"
- resolved "https://registry.yarnpkg.com/gcs-resumable-upload/-/gcs-resumable-upload-3.1.2.tgz#74ba51d791da397da6c856eabda7d059af724998"
- integrity sha512-VKWP3Xju1JmNX3N4ossnGp3DfIRZjOsMj8sDGPBGnvn8YSruCOVGQBvELfStfIFPybScv/e5sEdWx/qzfnS3+w==
- dependencies:
- abort-controller "^3.0.0"
- configstore "^5.0.0"
- extend "^3.0.2"
- gaxios "^4.0.0"
- google-auth-library "^6.0.0"
- pumpify "^2.0.0"
- stream-events "^1.0.4"
-
-get-proxy@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/get-proxy/-/get-proxy-2.1.0.tgz#349f2b4d91d44c4d4d4e9cba2ad90143fac5ef93"
- integrity sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==
- dependencies:
- npm-conf "^1.1.0"
-
-get-stdin@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe"
- integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=
-
-get-stream@3.0.0, get-stream@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
- integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=
-
-get-stream@^2.2.0:
- version "2.3.1"
- resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de"
- integrity sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=
- dependencies:
- object-assign "^4.0.1"
- pinkie-promise "^2.0.0"
-
-get-stream@^4.0.0, get-stream@^4.1.0:
- version "4.1.0"
- 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.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3"
- integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==
- dependencies:
- pump "^3.0.0"
-
-get-stream@^6.0.0:
- version "6.0.0"
- resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.0.tgz#3e0012cb6827319da2706e601a1583e8629a6718"
- integrity sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==
-
-get-uri@3:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-3.0.2.tgz#f0ef1356faabc70e1f9404fa3b66b2ba9bfc725c"
- integrity sha512-+5s0SJbGoyiJTZZ2JTpFPLMPSch72KEqGOTvQsBqg0RBWvwhWUSYZFAtz3TPW0GXJuLBJPts1E241iHg+VRfhg==
- dependencies:
- "@tootallnate/once" "1"
- data-uri-to-buffer "3"
- debug "4"
- file-uri-to-path "2"
- fs-extra "^8.1.0"
- ftp "^0.3.10"
-
-getpass@^0.1.1:
- version "0.1.7"
- resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
- integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=
- dependencies:
- assert-plus "^1.0.0"
-
-github-from-package@0.0.0:
- version "0.0.0"
- resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce"
- integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=
-
-glob-parent@^5.1.0, glob-parent@~5.1.0:
- version "5.1.2"
- 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-slash@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/glob-slash/-/glob-slash-1.0.0.tgz#fe52efa433233f74a2fe64c7abb9bc848202ab95"
- integrity sha1-/lLvpDMjP3Si/mTHq7m8hIICq5U=
-
-glob-slasher@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/glob-slasher/-/glob-slasher-1.0.1.tgz#747a0e5bb222642ee10d3e05443e109493cb0f8e"
- integrity sha1-dHoOW7IiZC7hDT4FRD4QlJPLD44=
- dependencies:
- glob-slash "^1.0.0"
- lodash.isobject "^2.4.1"
- toxic "^1.0.0"
-
-glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4:
- version "7.1.6"
- resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
- integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
- dependencies:
- fs.realpath "^1.0.0"
- inflight "^1.0.4"
- inherits "2"
- minimatch "^3.0.4"
- once "^1.3.0"
- path-is-absolute "^1.0.0"
-
-global-dirs@^2.0.1:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-2.1.0.tgz#e9046a49c806ff04d6c1825e196c8f0091e8df4d"
- integrity sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ==
- dependencies:
- ini "1.3.7"
-
-globby@^10.0.0:
- version "10.0.2"
- resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.2.tgz#277593e745acaa4646c3ab411289ec47a0392543"
- integrity sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==
- dependencies:
- "@types/glob" "^7.1.1"
- array-union "^2.1.0"
- dir-glob "^3.0.1"
- fast-glob "^3.0.3"
- glob "^7.1.3"
- ignore "^5.1.1"
- merge2 "^1.2.3"
- slash "^3.0.0"
-
-google-auth-library@^6.0.0, google-auth-library@^6.1.1, google-auth-library@^6.1.2, google-auth-library@^6.1.3:
- version "6.1.6"
- resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-6.1.6.tgz#deacdcdb883d9ed6bac78bb5d79a078877fdf572"
- integrity sha512-Q+ZjUEvLQj/lrVHF/IQwRo6p3s8Nc44Zk/DALsN+ac3T4HY/g/3rrufkgtl+nZ1TW7DNAw5cTChdVp4apUXVgQ==
- dependencies:
- arrify "^2.0.0"
- base64-js "^1.3.0"
- ecdsa-sig-formatter "^1.0.11"
- fast-text-encoding "^1.0.0"
- gaxios "^4.0.0"
- gcp-metadata "^4.2.0"
- gtoken "^5.0.4"
- jws "^4.0.0"
- lru-cache "^6.0.0"
-
-google-gax@^2.9.2:
- version "2.10.2"
- resolved "https://registry.yarnpkg.com/google-gax/-/google-gax-2.10.2.tgz#6d3dc047140e57987d0a2c2d9791faac9bc959b1"
- integrity sha512-adECud3d5jsk24SvPkKQG3Kw1szpy4We0OqKfsdBHKWlSWhdY4hVQEOG7iBBp469Zm327fzz7NZz8BMLOYZJHg==
- dependencies:
- "@grpc/grpc-js" "~1.2.0"
- "@grpc/proto-loader" "^0.5.1"
- "@types/long" "^4.0.0"
- abort-controller "^3.0.0"
- duplexify "^4.0.0"
- fast-text-encoding "^1.0.3"
- google-auth-library "^6.1.3"
- is-stream-ended "^0.1.4"
- node-fetch "^2.6.1"
- protobufjs "^6.10.2"
- retry-request "^4.0.0"
-
-google-p12-pem@^3.0.3:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/google-p12-pem/-/google-p12-pem-3.0.3.tgz#673ac3a75d3903a87f05878f3c75e06fc151669e"
- integrity sha512-wS0ek4ZtFx/ACKYF3JhyGe5kzH7pgiQ7J5otlumqR9psmWMYc+U9cErKlCYVYHoUaidXHdZ2xbo34kB+S+24hA==
- dependencies:
- node-forge "^0.10.0"
-
-got@^7.0.0:
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a"
- integrity sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==
- dependencies:
- decompress-response "^3.2.0"
- duplexer3 "^0.1.4"
- get-stream "^3.0.0"
- is-plain-obj "^1.1.0"
- is-retry-allowed "^1.0.0"
- is-stream "^1.0.0"
- isurl "^1.0.0-alpha5"
- lowercase-keys "^1.0.0"
- p-cancelable "^0.3.0"
- p-timeout "^1.1.1"
- safe-buffer "^5.0.1"
- timed-out "^4.0.0"
- url-parse-lax "^1.0.0"
- url-to-options "^1.0.1"
-
-got@^8.3.1:
- version "8.3.2"
- resolved "https://registry.yarnpkg.com/got/-/got-8.3.2.tgz#1d23f64390e97f776cac52e5b936e5f514d2e937"
- integrity sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==
- dependencies:
- "@sindresorhus/is" "^0.7.0"
- cacheable-request "^2.1.1"
- decompress-response "^3.3.0"
- duplexer3 "^0.1.4"
- get-stream "^3.0.0"
- into-stream "^3.1.0"
- is-retry-allowed "^1.1.0"
- isurl "^1.0.0-alpha5"
- lowercase-keys "^1.0.0"
- mimic-response "^1.0.0"
- p-cancelable "^0.4.0"
- p-timeout "^2.0.1"
- pify "^3.0.0"
- safe-buffer "^5.1.1"
- timed-out "^4.0.1"
- url-parse-lax "^3.0.0"
- url-to-options "^1.0.1"
-
-got@^9.6.0:
- version "9.6.0"
- 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"
- "@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@^4.1.10, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.3:
- version "4.2.4"
- resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
- integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==
-
-gtoken@^5.0.4:
- version "5.2.1"
- resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-5.2.1.tgz#4dae1fea17270f457954b4a45234bba5fc796d16"
- integrity sha512-OY0BfPKe3QnMsY9MzTHTSKn+Vl2l1CcLe6BwDEQj00mbbkl5nyQ/7EUREstg4fQNZ8iYE7br4JJ7TdKeDOPWmw==
- dependencies:
- gaxios "^4.0.0"
- google-p12-pem "^3.0.3"
- jws "^4.0.0"
-
-har-schema@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
- integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
-
-har-validator@~5.1.3:
- version "5.1.5"
- resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd"
- integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==
- dependencies:
- ajv "^6.12.3"
- har-schema "^2.0.0"
-
-has-ansi@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
- integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=
- dependencies:
- ansi-regex "^2.0.0"
-
-has-flag@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51"
- integrity sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=
-
-has-flag@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
- integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
-
-has-flag@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
- integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
-
-has-symbol-support-x@^1.4.1:
- version "1.4.2"
- resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455"
- integrity sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==
-
-has-to-string-tag-x@^1.2.0:
- version "1.4.1"
- resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d"
- integrity sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==
- dependencies:
- has-symbol-support-x "^1.4.1"
-
-has-unicode@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
- integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=
-
-has-yarn@^2.1.0:
- version "2.1.0"
- 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.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
- integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
- dependencies:
- function-bind "^1.1.1"
-
-hash-stream-validation@^0.2.2:
- version "0.2.4"
- resolved "https://registry.yarnpkg.com/hash-stream-validation/-/hash-stream-validation-0.2.4.tgz#ee68b41bf822f7f44db1142ec28ba9ee7ccb7512"
- integrity sha512-Gjzu0Xn7IagXVkSu9cSFuK1fqzwtLwFhNhVL8IFJijRNMgUttFbBSIAzKuSIrsFMO1+g1RlsoN49zPIbwPDMGQ==
-
-home-dir@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/home-dir/-/home-dir-1.0.0.tgz#2917eb44bdc9072ceda942579543847e3017fe4e"
- integrity sha1-KRfrRL3JByztqUJXlUOEfjAX/k4=
-
-hosted-git-info@^2.1.4:
- version "2.8.9"
- resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
- integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==
-
-http-cache-semantics@3.8.1:
- version "3.8.1"
- resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2"
- integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==
-
-http-cache-semantics@^4.0.0:
- version "4.1.0"
- 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.2:
- version "1.7.2"
- resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f"
- integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==
- dependencies:
- depd "~1.1.2"
- inherits "2.0.3"
- setprototypeof "1.1.1"
- statuses ">= 1.5.0 < 2"
- toidentifier "1.0.0"
-
-http-errors@1.7.3, http-errors@~1.7.2:
- version "1.7.3"
- resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06"
- 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"
-
-http-parser-js@>=0.5.1:
- version "0.5.3"
- resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.3.tgz#01d2709c79d41698bb01d4decc5e9da4e4a033d9"
- integrity sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==
-
-http-proxy-agent@^4.0.0, http-proxy-agent@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a"
- integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==
- dependencies:
- "@tootallnate/once" "1"
- agent-base "6"
- debug "4"
-
-http-signature@~1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
- integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=
- dependencies:
- assert-plus "^1.0.0"
- jsprim "^1.2.2"
- sshpk "^1.7.0"
-
-https-proxy-agent@5, https-proxy-agent@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2"
- integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==
- dependencies:
- agent-base "6"
- debug "4"
-
-human-signals@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3"
- integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==
-
-husky@^4.2.5:
- version "4.3.8"
- resolved "https://registry.yarnpkg.com/husky/-/husky-4.3.8.tgz#31144060be963fd6850e5cc8f019a1dfe194296d"
- integrity sha512-LCqqsB0PzJQ/AlCgfrfzRe3e3+NvmefAdKQhRYpxS4u6clblBoDdzzvHi8fmxKRzvMxPY/1WZWzomPZww0Anow==
- dependencies:
- chalk "^4.0.0"
- ci-info "^2.0.0"
- compare-versions "^3.6.0"
- cosmiconfig "^7.0.0"
- find-versions "^4.0.0"
- opencollective-postinstall "^2.0.2"
- pkg-dir "^5.0.0"
- please-upgrade-node "^3.2.0"
- slash "^3.0.0"
- which-pm-runs "^1.0.0"
-
-iconv-lite@0.4.24, iconv-lite@^0.4.24:
- version "0.4.24"
- resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
- integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
- dependencies:
- safer-buffer ">= 2.1.2 < 3"
-
-ieee754@^1.1.13:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
- integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
-
-ignore@^5.1.1, ignore@^5.1.4:
- version "5.1.8"
- resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57"
- integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==
-
-imagemin-mozjpeg@^9.0.0:
- version "9.0.0"
- resolved "https://registry.yarnpkg.com/imagemin-mozjpeg/-/imagemin-mozjpeg-9.0.0.tgz#d1af26d0b43d75a41c211051c1910da59d9d2324"
- integrity sha512-TwOjTzYqCFRgROTWpVSt5UTT0JeCuzF1jswPLKALDd89+PmrJ2PdMMYeDLYZ1fs9cTovI9GJd68mRSnuVt691w==
- dependencies:
- execa "^4.0.0"
- is-jpg "^2.0.0"
- mozjpeg "^7.0.0"
-
-imagemin-pngquant@^9.0.2:
- version "9.0.2"
- resolved "https://registry.yarnpkg.com/imagemin-pngquant/-/imagemin-pngquant-9.0.2.tgz#38155702b0cc4f60f671ba7c2b086ea3805d9567"
- integrity sha512-cj//bKo8+Frd/DM8l6Pg9pws1pnDUjgb7ae++sUX1kUVdv2nrngPykhiUOgFeE0LGY/LmUbCf4egCHC4YUcZSg==
- dependencies:
- execa "^4.0.0"
- is-png "^2.0.0"
- is-stream "^2.0.0"
- ow "^0.17.0"
- pngquant-bin "^6.0.0"
-
-imagemin@^7.0.1:
- version "7.0.1"
- resolved "https://registry.yarnpkg.com/imagemin/-/imagemin-7.0.1.tgz#f6441ca647197632e23db7d971fffbd530c87dbf"
- integrity sha512-33AmZ+xjZhg2JMCe+vDf6a9mzWukE7l+wAtesjE7KyteqqKjzxv7aVQeWnul1Ve26mWvEQqyPwl0OctNBfSR9w==
- dependencies:
- file-type "^12.0.0"
- globby "^10.0.0"
- graceful-fs "^4.2.2"
- junk "^3.1.0"
- make-dir "^3.0.0"
- p-pipe "^3.0.0"
- replace-ext "^1.0.0"
-
-import-fresh@^3.2.1:
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
- integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
- dependencies:
- parent-module "^1.0.0"
- resolve-from "^4.0.0"
-
-import-lazy@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43"
- integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=
-
-import-lazy@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-3.1.0.tgz#891279202c8a2280fdbd6674dbd8da1a1dfc67cc"
- integrity sha512-8/gvXvX2JMn0F+CDlSC4l6kOmVaLOO3XLkksI7CI3Ud95KDYJuYur2b9P/PUt/i/pDAMd/DulQsNbbbmRRsDIQ==
-
-imurmurhash@^0.1.4:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
- integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
-
-indent-string@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80"
- integrity sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=
- dependencies:
- repeating "^2.0.0"
-
-inflight@^1.0.4:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
- integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
- dependencies:
- once "^1.3.0"
- wrappy "1"
-
-inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
- integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
-
-inherits@2.0.3:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
- integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
-
-ini@1.3.7:
- version "1.3.7"
- resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.7.tgz#a09363e1911972ea16d7a8851005d84cf09a9a84"
- integrity sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==
-
-ini@^1.3.4, ini@~1.3.0:
- version "1.3.8"
- resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
- integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
-
-inquirer@~6.3.1:
- version "6.3.1"
- resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.3.1.tgz#7a413b5e7950811013a3db491c61d1f3b776e8e7"
- integrity sha512-MmL624rfkFt4TG9y/Jvmt8vdmOo836U7Y0Hxr2aFk3RelZEGX4Igk0KabWrcaaZaTv9uzglOqWh1Vly+FAWAXA==
- dependencies:
- ansi-escapes "^3.2.0"
- chalk "^2.4.2"
- cli-cursor "^2.1.0"
- cli-width "^2.0.0"
- external-editor "^3.0.3"
- figures "^2.0.0"
- lodash "^4.17.11"
- mute-stream "0.0.7"
- run-async "^2.2.0"
- rxjs "^6.4.0"
- string-width "^2.1.0"
- strip-ansi "^5.1.0"
- through "^2.3.6"
-
-install-artifact-from-github@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/install-artifact-from-github/-/install-artifact-from-github-1.2.0.tgz#adcbd123c16a4337ec44ea76d0ebf253cc16b074"
- integrity sha512-3OxCPcY55XlVM3kkfIpeCgmoSKnMsz2A3Dbhsq0RXpIknKQmrX1YiznCeW9cD2ItFmDxziA3w6Eg8d80AoL3oA==
-
-into-stream@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/into-stream/-/into-stream-3.1.0.tgz#96fb0a936c12babd6ff1752a17d05616abd094c6"
- integrity sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=
- dependencies:
- from2 "^2.1.1"
- p-is-promise "^1.1.0"
-
-ip-regex@^4.1.0:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-4.3.0.tgz#687275ab0f57fa76978ff8f4dddc8a23d5990db5"
- integrity sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==
-
-ip@^1.1.5:
- version "1.1.5"
- resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
- integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=
-
-ipaddr.js@1.9.1:
- version "1.9.1"
- resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
- integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==
-
-is-arrayish@^0.2.1:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
- integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=
-
-is-arrayish@^0.3.1:
- version "0.3.2"
- resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03"
- integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==
-
-is-binary-path@~2.1.0:
- version "2.1.0"
- 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-ci@^2.0.0:
- version "2.0.0"
- 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.1.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.2.0.tgz#97037ef3d52224d85163f5597b2b63d9afed981a"
- integrity sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==
- dependencies:
- has "^1.0.3"
-
-is-extglob@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
- integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
-
-is-finite@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3"
- integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==
-
-is-fullwidth-code-point@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
- integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs=
- dependencies:
- number-is-nan "^1.0.0"
-
-is-fullwidth-code-point@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
- integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=
-
-is-fullwidth-code-point@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
- integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
-
-is-glob@^4.0.1, is-glob@~4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc"
- integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==
- dependencies:
- is-extglob "^2.1.1"
-
-is-installed-globally@^0.3.1:
- version "0.3.2"
- 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"
- is-path-inside "^3.0.1"
-
-is-jpg@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/is-jpg/-/is-jpg-2.0.0.tgz#2e1997fa6e9166eaac0242daae443403e4ef1d97"
- integrity sha1-LhmX+m6RZuqsAkLarkQ0A+TvHZc=
-
-is-natural-number@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8"
- integrity sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=
-
-is-npm@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-4.0.0.tgz#c90dd8380696df87a7a6d823c20d0b12bbe3c84d"
- integrity sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==
-
-is-number@^7.0.0:
- version "7.0.0"
- 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.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982"
- integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==
-
-is-object@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.2.tgz#a56552e1c665c9e950b4a025461da87e72f86fcf"
- integrity sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==
-
-is-path-inside@^3.0.1:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.2.tgz#f5220fc82a3e233757291dddc9c5877f2a1f3017"
- integrity sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg==
-
-is-plain-obj@^1.0.0, 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 sha1-caUMhCnfync8kqOQpKA7OfzVHT4=
-
-is-png@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/is-png/-/is-png-2.0.0.tgz#ee8cbc9e9b050425cedeeb4a6fb74a649b0a4a8d"
- integrity sha512-4KPGizaVGj2LK7xwJIz8o5B2ubu1D/vcQsgOGFEDlpcvgZHto4gBnyd0ig7Ws+67ixmwKoNmu0hYnpo6AaKb5g==
-
-is-promise@^2.2.2:
- version "2.2.2"
- resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1"
- integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==
-
-is-retry-allowed@^1.0.0, is-retry-allowed@^1.1.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4"
- integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==
-
-is-stream-ended@^0.1.4:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/is-stream-ended/-/is-stream-ended-0.1.4.tgz#f50224e95e06bce0e356d440a4827cd35b267eda"
- integrity sha512-xj0XPvmr7bQFTvirqnFr50o0hQIh6ZItDqloxt5aJrR4NQsYeSsyFQERYGCAzfindAcnKjINnwEEgLx4IqVzQw==
-
-is-stream@^1.0.0, is-stream@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
- integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
-
-is-stream@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3"
- integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==
-
-is-typedarray@^1.0.0, is-typedarray@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
- integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
-
-is-url@^1.2.2, is-url@^1.2.4:
- version "1.2.4"
- resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52"
- integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==
-
-is-utf8@^0.2.0:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
- integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=
-
-is-wsl@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d"
- integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=
-
-is-yarn-global@^0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232"
- integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==
-
-is2@^2.0.6:
- version "2.0.6"
- resolved "https://registry.yarnpkg.com/is2/-/is2-2.0.6.tgz#094f887248b49ba7ce278f8c39f85a70927bb5de"
- integrity sha512-+Z62OHOjA6k2sUDOKXoZI3EXv7Fb1K52jpTBLbkfx62bcUeSsrTBLhEquCRDKTx0XE5XbHcG/S2vrtE3lnEDsQ==
- dependencies:
- deep-is "^0.1.3"
- ip-regex "^4.1.0"
- is-url "^1.2.4"
-
-isarray@0.0.1:
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
- integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=
-
-isarray@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
- integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
-
-isexe@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
- integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
-
-isstream@~0.1.2:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
- integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
-
-isurl@^1.0.0-alpha5:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67"
- integrity sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==
- dependencies:
- has-to-string-tag-x "^1.2.0"
- is-object "^1.0.1"
-
-jju@^1.1.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/jju/-/jju-1.4.0.tgz#a3abe2718af241a2b2904f84a625970f389ae32a"
- integrity sha1-o6vicYryQaKykE+EpiWXDzia4yo=
-
-join-path@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/join-path/-/join-path-1.1.1.tgz#10535a126d24cbd65f7ffcdf15ef2e631076b505"
- integrity sha1-EFNaEm0ky9Zff/zfFe8uYxB2tQU=
- dependencies:
- as-array "^2.0.0"
- url-join "0.0.1"
- valid-url "^1"
-
-js-tokens@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
- integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
-
-js-yaml@^3.13.1:
- version "3.14.1"
- resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537"
- integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==
- dependencies:
- argparse "^1.0.7"
- esprima "^4.0.0"
-
-jsbn@~0.1.0:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
- integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
-
-json-bigint@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/json-bigint/-/json-bigint-1.0.0.tgz#ae547823ac0cad8398667f8cd9ef4730f5b01ff1"
- integrity sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==
- dependencies:
- bignumber.js "^9.0.0"
-
-json-buffer@3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898"
- integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=
-
-json-parse-even-better-errors@^2.3.0:
- version "2.3.1"
- 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-parse-helpfulerror@^1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/json-parse-helpfulerror/-/json-parse-helpfulerror-1.0.3.tgz#13f14ce02eed4e981297b64eb9e3b932e2dd13dc"
- integrity sha1-E/FM4C7tTpgSl7ZOueO5MuLdE9w=
- dependencies:
- jju "^1.1.0"
-
-json-ptr@^1.3.1:
- version "1.3.2"
- resolved "https://registry.yarnpkg.com/json-ptr/-/json-ptr-1.3.2.tgz#17f45b322a843b1f2fbcc9b45132bd9b3ba8cd38"
- integrity sha512-tFH40YQ+lG7mgYYM1kGZOhQngO4SbOEHZJlA4W+NtetWZ20EUU3BPU+30uWRKumuAJoSo5eqrsXD2h72ioS8ew==
- dependencies:
- tslib "^2.0.0"
-
-json-schema-traverse@^0.4.1:
- version "0.4.1"
- resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
- integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
-
-json-schema@0.2.3:
- version "0.2.3"
- resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
- integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
-
-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 sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
-
-jsonfile@^2.1.0:
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8"
- integrity sha1-NzaitCi4e72gzIO1P6PWM6NcKug=
- optionalDependencies:
- graceful-fs "^4.1.6"
-
-jsonfile@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
- integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=
- optionalDependencies:
- graceful-fs "^4.1.6"
-
-jsonparse@^1.2.0:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
- integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=
-
-jsonschema@^1.0.2:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.4.0.tgz#1afa34c4bc22190d8e42271ec17ac8b3404f87b2"
- integrity sha512-/YgW6pRMr6M7C+4o8kS+B/2myEpHCrxO4PEWnqJNBFMjn7EWXqlQ4tGwL6xTHeRplwuZmcAncdvfOad1nT2yMw==
-
-jsonwebtoken@^8.2.1, jsonwebtoken@^8.5.1:
- version "8.5.1"
- resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d"
- 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"
-
-jsprim@^1.2.2:
- version "1.4.1"
- resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
- integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=
- dependencies:
- assert-plus "1.0.0"
- extsprintf "1.3.0"
- json-schema "0.2.3"
- verror "1.10.0"
-
-junk@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/junk/-/junk-3.1.0.tgz#31499098d902b7e98c5d9b9c80f43457a88abfa1"
- integrity sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ==
-
-jwa@^1.4.1:
- version "1.4.1"
- 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"
- ecdsa-sig-formatter "1.0.11"
- safe-buffer "^5.0.1"
-
-jwa@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/jwa/-/jwa-2.0.0.tgz#a7e9c3f29dae94027ebcaf49975c9345593410fc"
- integrity sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==
- dependencies:
- buffer-equal-constant-time "1.0.1"
- ecdsa-sig-formatter "1.0.11"
- safe-buffer "^5.0.1"
-
-jws@^3.2.2:
- version "3.2.2"
- resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304"
- integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==
- dependencies:
- jwa "^1.4.1"
- safe-buffer "^5.0.1"
-
-jws@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/jws/-/jws-4.0.0.tgz#2d4e8cf6a318ffaa12615e9dec7e86e6c97310f4"
- integrity sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==
- dependencies:
- jwa "^2.0.0"
- safe-buffer "^5.0.1"
-
-keyv@3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.0.0.tgz#44923ba39e68b12a7cec7df6c3268c031f2ef373"
- integrity sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==
- dependencies:
- json-buffer "3.0.0"
-
-keyv@^3.0.0:
- version "3.1.0"
- 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"
-
-kuler@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3"
- integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==
-
-latest-version@^5.0.0:
- version "5.1.0"
- 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"
-
-lazystream@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4"
- integrity sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=
- dependencies:
- readable-stream "^2.0.5"
-
-leven@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2"
- integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==
-
-levn@~0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
- integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=
- dependencies:
- prelude-ls "~1.1.2"
- type-check "~0.3.2"
-
-lines-and-columns@^1.1.6:
- version "1.1.6"
- resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00"
- integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=
-
-listenercount@~1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/listenercount/-/listenercount-1.0.1.tgz#84c8a72ab59c4725321480c975e6508342e70937"
- integrity sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=
-
-load-json-file@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
- integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=
- dependencies:
- graceful-fs "^4.1.2"
- parse-json "^2.2.0"
- pify "^2.0.0"
- pinkie-promise "^2.0.0"
- strip-bom "^2.0.0"
-
-locate-path@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
- integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==
- dependencies:
- p-locate "^4.1.0"
-
-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._isnative@~2.4.1:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/lodash._isnative/-/lodash._isnative-2.4.1.tgz#3ea6404b784a7be836c7b57580e1cdf79b14832c"
- integrity sha1-PqZAS3hKe+g2x7V1gOHN95sUgyw=
-
-lodash._objecttypes@~2.4.1:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz#7c0b7f69d98a1f76529f890b0cdb1b4dfec11c11"
- integrity sha1-fAt/admKH3ZSn4kLDNsbTf7BHBE=
-
-lodash._shimkeys@~2.4.1:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz#6e9cc9666ff081f0b5a6c978b83e242e6949d203"
- integrity sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=
- dependencies:
- lodash._objecttypes "~2.4.1"
-
-lodash.camelcase@^4.3.0:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
- integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY=
-
-lodash.defaults@^4.2.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
- integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=
-
-lodash.difference@^4.5.0:
- version "4.5.0"
- resolved "https://registry.yarnpkg.com/lodash.difference/-/lodash.difference-4.5.0.tgz#9ccb4e505d486b91651345772885a2df27fd017c"
- integrity sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=
-
-lodash.flatten@^4.4.0:
- version "4.4.0"
- resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f"
- integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=
-
-lodash.includes@^4.3.0:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f"
- integrity sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=
-
-lodash.isarguments@2.4.x:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-2.4.1.tgz#4931a9c08253adf091ae7ca192258a973876ecca"
- integrity sha1-STGpwIJTrfCRrnyhkiWKlzh27Mo=
-
-lodash.isarguments@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a"
- integrity sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=
-
-lodash.isboolean@^3.0.3:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6"
- integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=
-
-lodash.isinteger@^4.0.4:
- version "4.0.4"
- resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343"
- integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=
-
-lodash.isnumber@^3.0.3:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc"
- integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=
-
-lodash.isobject@^2.4.1, lodash.isobject@~2.4.1:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/lodash.isobject/-/lodash.isobject-2.4.1.tgz#5a2e47fe69953f1ee631a7eba1fe64d2d06558f5"
- integrity sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=
- dependencies:
- lodash._objecttypes "~2.4.1"
-
-lodash.isobject@^3.0.0:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/lodash.isobject/-/lodash.isobject-3.0.2.tgz#3c8fb8d5b5bf4bf90ae06e14f2a530a4ed935e1d"
- integrity sha1-PI+41bW/S/kK4G4U8qUwpO2TXh0=
-
-lodash.isplainobject@^4.0.6:
- version "4.0.6"
- resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
- integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=
-
-lodash.isstring@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451"
- integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=
-
-lodash.keys@~2.4.1:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-2.4.1.tgz#48dea46df8ff7632b10d706b8acb26591e2b3727"
- integrity sha1-SN6kbfj/djKxDXBrissmWR4rNyc=
- dependencies:
- lodash._isnative "~2.4.1"
- lodash._shimkeys "~2.4.1"
- lodash.isobject "~2.4.1"
-
-lodash.once@^4.0.0:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
- integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=
-
-lodash.snakecase@^4.1.1:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz#39d714a35357147837aefd64b5dcbb16becd8f8d"
- integrity sha1-OdcUo1NXFHg3rv1ktdy7Fr7Nj40=
-
-lodash.toarray@^4.4.0:
- version "4.4.0"
- resolved "https://registry.yarnpkg.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz#24c4bfcd6b2fba38bfd0594db1179d8e9b656561"
- integrity sha1-JMS/zWsvuji/0FlNsRedjptlZWE=
-
-lodash.union@^4.6.0:
- version "4.6.0"
- resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88"
- integrity sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=
-
-lodash.values@^2.4.1:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/lodash.values/-/lodash.values-2.4.1.tgz#abf514436b3cb705001627978cbcf30b1280eea4"
- integrity sha1-q/UUQ2s8twUAFieXjLzzCxKA7qQ=
- dependencies:
- lodash.keys "~2.4.1"
-
-lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.19, lodash@^4.17.21, lodash@^4.17.5:
- version "4.17.21"
- resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
- integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
-
-log-symbols@^2.2.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a"
- integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==
- dependencies:
- chalk "^2.0.1"
-
-logalot@^2.0.0, logalot@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/logalot/-/logalot-2.1.0.tgz#5f8e8c90d304edf12530951a5554abb8c5e3f552"
- integrity sha1-X46MkNME7fElMJUaVVSruMXj9VI=
- dependencies:
- figures "^1.3.5"
- squeak "^1.0.0"
-
-logform@^2.2.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/logform/-/logform-2.2.0.tgz#40f036d19161fc76b68ab50fdc7fe495544492f2"
- integrity sha512-N0qPlqfypFx7UHNn4B3lzS/b0uLqt2hmuoa+PpuXNYgozdJYAyauF5Ky0BWVjrxDlMWiT3qN4zPq3vVAfZy7Yg==
- dependencies:
- colors "^1.2.1"
- fast-safe-stringify "^2.0.4"
- fecha "^4.2.0"
- ms "^2.1.1"
- triple-beam "^1.3.0"
-
-long@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28"
- integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==
-
-longest@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
- integrity sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=
-
-loud-rejection@^1.0.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f"
- integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=
- dependencies:
- currently-unhandled "^0.4.1"
- signal-exit "^3.0.0"
-
-lowercase-keys@1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306"
- integrity sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=
-
-lowercase-keys@^1.0.0, lowercase-keys@^1.0.1:
- version "1.0.1"
- 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.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479"
- integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==
-
-lpad-align@^1.0.1:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/lpad-align/-/lpad-align-1.1.2.tgz#21f600ac1c3095c3c6e497ee67271ee08481fe9e"
- integrity sha1-IfYArBwwlcPG5JfuZyce4ISB/p4=
- dependencies:
- get-stdin "^4.0.1"
- indent-string "^2.1.0"
- longest "^1.0.0"
- meow "^3.3.0"
-
-lru-cache@^4.0.1:
- version "4.1.5"
- 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"
- yallist "^2.1.2"
-
-lru-cache@^5.1.1:
- version "5.1.1"
- resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
- integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==
- dependencies:
- yallist "^3.0.2"
-
-lru-cache@^6.0.0:
- version "6.0.0"
- resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
- integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
- dependencies:
- yallist "^4.0.0"
-
-lru-queue@^0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3"
- integrity sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=
- dependencies:
- es5-ext "~0.10.2"
-
-make-dir@^1.0.0, make-dir@^1.2.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c"
- integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==
- dependencies:
- pify "^3.0.0"
-
-make-dir@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f"
- integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==
- dependencies:
- semver "^6.0.0"
-
-make-error@^1.1.1:
- version "1.3.6"
- resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
- integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
-
-map-obj@^1.0.0, map-obj@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
- integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=
-
-marked-terminal@^3.3.0:
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/marked-terminal/-/marked-terminal-3.3.0.tgz#25ce0c0299285998c7636beaefc87055341ba1bd"
- integrity sha512-+IUQJ5VlZoAFsM5MHNT7g3RHSkA3eETqhRCdXv4niUMAKHQ7lb1yvAcuGPmm4soxhmtX13u4Li6ZToXtvSEH+A==
- dependencies:
- ansi-escapes "^3.1.0"
- cardinal "^2.1.1"
- chalk "^2.4.1"
- cli-table "^0.3.1"
- node-emoji "^1.4.1"
- supports-hyperlinks "^1.0.1"
-
-marked@^0.7.0:
- version "0.7.0"
- resolved "https://registry.yarnpkg.com/marked/-/marked-0.7.0.tgz#b64201f051d271b1edc10a04d1ae9b74bb8e5c0e"
- integrity sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg==
-
-media-typer@0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
- integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
-
-memoizee@^0.4.14:
- version "0.4.15"
- resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.15.tgz#e6f3d2da863f318d02225391829a6c5956555b72"
- integrity sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==
- dependencies:
- d "^1.0.1"
- es5-ext "^0.10.53"
- es6-weak-map "^2.0.3"
- event-emitter "^0.3.5"
- is-promise "^2.2.2"
- lru-queue "^0.1.0"
- next-tick "^1.1.0"
- timers-ext "^0.1.7"
-
-meow@^3.3.0:
- version "3.7.0"
- resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb"
- integrity sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=
- dependencies:
- 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"
-
-merge-descriptors@1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
- integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=
-
-merge-stream@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
- integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
-
-merge2@^1.2.3, merge2@^1.3.0:
- version "1.4.1"
- resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
- integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
-
-methods@~1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
- integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
-
-micromatch@^4.0.2:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259"
- integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==
- dependencies:
- braces "^3.0.1"
- picomatch "^2.0.5"
-
-mime-db@1.45.0, "mime-db@>= 1.43.0 < 2", mime-db@^1.28.0:
- version "1.45.0"
- resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea"
- integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==
-
-mime-types@^2.0.8, mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.19, mime-types@~2.1.24:
- version "2.1.28"
- resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.28.tgz#1160c4757eab2c5363888e005273ecf79d2a0ecd"
- integrity sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==
- dependencies:
- mime-db "1.45.0"
-
-mime@1.6.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
- integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
-
-mime@^2.2.0:
- version "2.5.0"
- resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.0.tgz#2b4af934401779806ee98026bb42e8c1ae1876b1"
- integrity sha512-ft3WayFSFUVBuJj7BMLKAQcSlItKtfjsKDDsii3rqFDAZ7t11zRe8ASw/GlmivGwVUYtwkQrxiGGpL6gFvB0ag==
-
-mimic-fn@^1.0.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
- integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==
-
-mimic-fn@^2.1.0:
- version "2.1.0"
- 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.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.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43"
- 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.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
- integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
- dependencies:
- brace-expansion "^1.1.7"
-
-minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5:
- version "1.2.5"
- resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
- integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
-
-minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0:
- version "2.9.0"
- resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6"
- integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==
- dependencies:
- safe-buffer "^5.1.2"
- yallist "^3.0.0"
-
-minipass@^3.0.0:
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.3.tgz#7d42ff1f39635482e15f9cdb53184deebd5815fd"
- integrity sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==
- dependencies:
- yallist "^4.0.0"
-
-minizlib@^1.2.1:
- version "1.3.3"
- resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d"
- integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==
- dependencies:
- minipass "^2.9.0"
-
-minizlib@^2.1.1:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
- integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==
- dependencies:
- minipass "^3.0.0"
- yallist "^4.0.0"
-
-mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3:
- version "0.5.3"
- resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113"
- integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==
-
-"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.3, mkdirp@^0.5.5:
- version "0.5.5"
- resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
- integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
- dependencies:
- minimist "^1.2.5"
-
-mkdirp@^1.0.3:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
- integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
-
-morgan@^1.10.0, morgan@^1.8.2:
- version "1.10.0"
- resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.10.0.tgz#091778abc1fc47cd3509824653dae1faab6b17d7"
- integrity sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==
- dependencies:
- basic-auth "~2.0.1"
- debug "2.6.9"
- depd "~2.0.0"
- on-finished "~2.3.0"
- on-headers "~1.0.2"
-
-mozjpeg@^7.0.0:
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/mozjpeg/-/mozjpeg-7.0.0.tgz#c20f67a538fcaaa388d325875c53c0e7bc432f7d"
- integrity sha512-mH7atSbIusVTO3A4H43sEdmveN3aWn54k6V0edefzCEvOsTrbjg5murY2TsNznaztWnIgaRbWxeLVp4IgKdedQ==
- dependencies:
- bin-build "^3.0.0"
- bin-wrapper "^4.0.0"
- logalot "^2.1.0"
-
-mri@^1.1.5:
- version "1.1.6"
- resolved "https://registry.yarnpkg.com/mri/-/mri-1.1.6.tgz#49952e1044db21dbf90f6cd92bc9c9a777d415a6"
- integrity sha512-oi1b3MfbyGa7FJMP9GmLTttni5JoICpYBRlq+x5V16fZbLsnL9N3wFqqIm/nIG43FjUFkFh9Epzp/kzUGUnJxQ==
-
-ms@2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
- integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
-
-ms@2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
- integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
-
-ms@2.1.2:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
- integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
-
-ms@^2.1.1:
- version "2.1.3"
- resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
- integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
-
-multimatch@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-4.0.0.tgz#8c3c0f6e3e8449ada0af3dd29efb491a375191b3"
- integrity sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==
- dependencies:
- "@types/minimatch" "^3.0.3"
- array-differ "^3.0.0"
- array-union "^2.1.0"
- arrify "^2.0.1"
- minimatch "^3.0.4"
-
-mute-stream@0.0.7:
- version "0.0.7"
- resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
- integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=
-
-nan@^2.14.2:
- version "2.14.2"
- resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19"
- integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==
-
-napi-build-utils@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806"
- integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==
-
-nash@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/nash/-/nash-3.0.0.tgz#bced3a0cb8434c2ad30d1a0d567cfc0c37128eea"
- integrity sha512-M5SahEycXUmko3zOvsBkF6p94CWLhnyy9hfpQ9Qzp+rQkQ8D1OaTlfTl1OBWktq9Fak3oDXKU+ev7tiMaMu+1w==
- dependencies:
- async "^1.3.0"
- flat-arguments "^1.0.0"
- lodash "^4.17.5"
- minimist "^1.1.0"
-
-negotiator@0.6.2:
- version "0.6.2"
- resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
- integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
-
-netmask@^1.0.6:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/netmask/-/netmask-1.0.6.tgz#20297e89d86f6f6400f250d9f4f6b4c1945fcd35"
- integrity sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=
-
-next-tick@1, next-tick@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb"
- integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==
-
-next-tick@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c"
- integrity sha1-yobR/ogoFpsBICCOPchCS524NCw=
-
-nice-try@^1.0.4:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
- integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
-
-node-abi@^2.7.0:
- version "2.19.3"
- resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.19.3.tgz#252f5dcab12dad1b5503b2d27eddd4733930282d"
- integrity sha512-9xZrlyfvKhWme2EXFKQhZRp1yNWT/uI1luYPr3sFl+H4keYY4xR+1jO7mvTTijIsHf1M+QDe9uWuKeEpLInIlg==
- dependencies:
- semver "^5.4.1"
-
-node-addon-api@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.1.0.tgz#98b21931557466c6729e51cb77cd39c965f42239"
- integrity sha512-flmrDNB06LIl5lywUz7YlNGZH/5p0M7W28k8hzd9Lshtdh1wshD2Y+U4h9LD6KObOy1f+fEVdgprPrEymjM5uw==
-
-node-emoji@^1.4.1:
- version "1.10.0"
- resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.10.0.tgz#8886abd25d9c7bb61802a658523d1f8d2a89b2da"
- integrity sha512-Yt3384If5H6BYGVHiHwTL+99OzJKHhgp82S8/dktEK73T26BazdgZ4JZh92xSVtGNJvz9UbXdNAc5hcrXV42vw==
- dependencies:
- lodash.toarray "^4.4.0"
-
-node-fetch@^2.3.0, node-fetch@^2.6.1:
- version "2.6.1"
- resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
- integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
-
-node-forge@^0.10.0:
- version "0.10.0"
- resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3"
- integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==
-
-node-gyp@^7.1.2:
- version "7.1.2"
- resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-7.1.2.tgz#21a810aebb187120251c3bcec979af1587b188ae"
- integrity sha512-CbpcIo7C3eMu3dL1c3d0xw449fHIGALIJsRP4DDPHpyiW8vcriNY7ubh9TE4zEKfSxscY7PjeFnshE7h75ynjQ==
- dependencies:
- env-paths "^2.2.0"
- glob "^7.1.4"
- graceful-fs "^4.2.3"
- nopt "^5.0.0"
- npmlog "^4.1.2"
- request "^2.88.2"
- rimraf "^3.0.2"
- semver "^7.3.2"
- tar "^6.0.2"
- which "^2.0.2"
-
-noop-logger@^0.1.1:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2"
- integrity sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=
-
-nopt@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88"
- integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==
- dependencies:
- abbrev "1"
-
-normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
- version "2.5.0"
- resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
- integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==
- dependencies:
- hosted-git-info "^2.1.4"
- resolve "^1.10.0"
- semver "2 || 3 || 4 || 5"
- validate-npm-package-license "^3.0.1"
-
-normalize-path@^3.0.0, normalize-path@~3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
- integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
-
-normalize-url@2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-2.0.1.tgz#835a9da1551fa26f70e92329069a23aa6574d7e6"
- integrity sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==
- dependencies:
- prepend-http "^2.0.0"
- query-string "^5.0.1"
- sort-keys "^2.0.0"
-
-normalize-url@^4.1.0:
- version "4.5.0"
- resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129"
- integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==
-
-npm-conf@^1.1.0:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/npm-conf/-/npm-conf-1.1.3.tgz#256cc47bd0e218c259c4e9550bf413bc2192aff9"
- integrity sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==
- dependencies:
- config-chain "^1.1.11"
- pify "^3.0.0"
-
-npm-run-path@^2.0.0:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
- integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=
- dependencies:
- path-key "^2.0.0"
-
-npm-run-path@^4.0.0:
- version "4.0.1"
- 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.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
- 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"
-
-number-is-nan@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
- integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
-
-oauth-sign@~0.9.0:
- version "0.9.0"
- resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
- integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
-
-object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
- integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
-
-on-finished@^2.2.0, on-finished@~2.3.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
- integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=
- dependencies:
- ee-first "1.1.1"
-
-on-headers@^1.0.0, on-headers@~1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f"
- integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==
-
-once@^1.3.0, once@^1.3.1, once@^1.4.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
- integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
- dependencies:
- wrappy "1"
-
-one-time@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/one-time/-/one-time-1.0.0.tgz#e06bc174aed214ed58edede573b433bbf827cb45"
- integrity sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==
- dependencies:
- fn.name "1.x.x"
-
-onetime@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4"
- integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=
- dependencies:
- mimic-fn "^1.0.0"
-
-onetime@^5.1.0:
- version "5.1.2"
- resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
- integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
- dependencies:
- mimic-fn "^2.1.0"
-
-open@^6.3.0:
- version "6.4.0"
- resolved "https://registry.yarnpkg.com/open/-/open-6.4.0.tgz#5c13e96d0dc894686164f18965ecfe889ecfc8a9"
- integrity sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg==
- dependencies:
- is-wsl "^1.1.0"
-
-openapi3-ts@^1.2.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/openapi3-ts/-/openapi3-ts-1.4.0.tgz#679d5a24be0efc36f5de4fc2c4b8513663e16f65"
- integrity sha512-8DmE2oKayvSkIR3XSZ4+pRliBsx19bSNeIzkTPswY8r4wvjX86bMxsORdqwAwMxE8PefOcSAT2auvi/0TZe9yA==
-
-opencollective-postinstall@^2.0.2:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz#7a0fff978f6dbfa4d006238fbac98ed4198c3259"
- integrity sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==
-
-optionator@^0.8.1:
- version "0.8.3"
- resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
- integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==
- 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"
-
-ora@^3.4.0:
- version "3.4.0"
- resolved "https://registry.yarnpkg.com/ora/-/ora-3.4.0.tgz#bf0752491059a3ef3ed4c85097531de9fdbcd318"
- integrity sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg==
- dependencies:
- chalk "^2.4.2"
- cli-cursor "^2.1.0"
- cli-spinners "^2.0.0"
- log-symbols "^2.2.0"
- strip-ansi "^5.2.0"
- wcwidth "^1.0.1"
-
-os-filter-obj@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/os-filter-obj/-/os-filter-obj-2.0.0.tgz#1c0b62d5f3a2442749a2d139e6dddee6e81d8d16"
- integrity sha512-uksVLsqG3pVdzzPvmAHpBK0wKxYItuzZr7SziusRPoz67tGV8rL1szZ6IdeUrbqLjGDwApBtN29eEE3IqGHOjg==
- dependencies:
- arch "^2.1.0"
-
-os-tmpdir@~1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
- integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
-
-ow@^0.17.0:
- version "0.17.0"
- resolved "https://registry.yarnpkg.com/ow/-/ow-0.17.0.tgz#4f938999fed6264c9048cd6254356e0f1e7f688c"
- integrity sha512-i3keDzDQP5lWIe4oODyDFey1qVrq2hXKTuTH2VpqwpYtzPiKZt2ziRI4NBQmgW40AnV5Euz17OyWweCb+bNEQA==
- dependencies:
- type-fest "^0.11.0"
-
-p-cancelable@^0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa"
- integrity sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==
-
-p-cancelable@^0.4.0:
- version "0.4.1"
- resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.4.1.tgz#35f363d67d52081c8d9585e37bcceb7e0bbcb2a0"
- integrity sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==
-
-p-cancelable@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc"
- integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==
-
-p-defer@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-3.0.0.tgz#d1dceb4ee9b2b604b1d94ffec83760175d4e6f83"
- integrity sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw==
-
-p-event@^1.0.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/p-event/-/p-event-1.3.0.tgz#8e6b4f4f65c72bc5b6fe28b75eda874f96a4a085"
- integrity sha1-jmtPT2XHK8W2/ii3XtqHT5akoIU=
- dependencies:
- p-timeout "^1.1.1"
-
-p-event@^2.1.0:
- version "2.3.1"
- resolved "https://registry.yarnpkg.com/p-event/-/p-event-2.3.1.tgz#596279ef169ab2c3e0cae88c1cfbb08079993ef6"
- integrity sha512-NQCqOFhbpVTMX4qMe8PF8lbGtzZ+LCiN7pcNrb/413Na7+TRoe1xkKUzuWa/YEJdGQ0FvKtj35EEbDoVPO2kbA==
- dependencies:
- p-timeout "^2.0.1"
-
-p-finally@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
- integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=
-
-p-is-promise@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e"
- integrity sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=
-
-p-limit@^2.2.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
- integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==
- dependencies:
- p-try "^2.0.0"
-
-p-limit@^3.0.1, p-limit@^3.0.2:
- 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.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-series@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/p-map-series/-/p-map-series-1.0.0.tgz#bf98fe575705658a9e1351befb85ae4c1f07bdca"
- integrity sha1-v5j+V1cFZYqeE1G++4WuTB8Hvco=
- dependencies:
- p-reduce "^1.0.0"
-
-p-pipe@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/p-pipe/-/p-pipe-3.1.0.tgz#48b57c922aa2e1af6a6404cb7c6bf0eb9cc8e60e"
- integrity sha512-08pj8ATpzMR0Y80x50yJHn37NF6vjrqHutASaX5LiH5npS9XPvrUmscd9MF5R4fuYRHOxQR1FfMIlF7AzwoPqw==
-
-p-queue@^6.6.1:
- version "6.6.2"
- resolved "https://registry.yarnpkg.com/p-queue/-/p-queue-6.6.2.tgz#2068a9dcf8e67dd0ec3e7a2bcb76810faa85e426"
- integrity sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==
- dependencies:
- eventemitter3 "^4.0.4"
- p-timeout "^3.2.0"
-
-p-reduce@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa"
- integrity sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=
-
-p-retry@^4.0.0:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.3.0.tgz#a31679a66b0261a51fa6c43b19b6f4471a54021e"
- integrity sha512-Pow4yaHpOiJou1QcpGcBJhGHiS4782LdDa6GhU91hlaNh3ExOOupjSJcxPQZYmUSZk3Pl2ARz/LRvW8Qu0+3mQ==
- dependencies:
- "@types/retry" "^0.12.0"
- retry "^0.12.0"
-
-p-timeout@^1.1.1:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386"
- integrity sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=
- dependencies:
- p-finally "^1.0.0"
-
-p-timeout@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-2.0.1.tgz#d8dd1979595d2dc0139e1fe46b8b646cb3cdf038"
- integrity sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==
- dependencies:
- p-finally "^1.0.0"
-
-p-timeout@^3.2.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.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
- integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
-
-pac-proxy-agent@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-4.1.0.tgz#66883eeabadc915fc5e95457324cb0f0ac78defb"
- integrity sha512-ejNgYm2HTXSIYX9eFlkvqFp8hyJ374uDf0Zq5YUAifiSh1D6fo+iBivQZirGvVv8dCYUsLhmLBRhlAYvBKI5+Q==
- dependencies:
- "@tootallnate/once" "1"
- agent-base "6"
- debug "4"
- get-uri "3"
- http-proxy-agent "^4.0.1"
- https-proxy-agent "5"
- pac-resolver "^4.1.0"
- raw-body "^2.2.0"
- socks-proxy-agent "5"
-
-pac-resolver@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/pac-resolver/-/pac-resolver-4.1.0.tgz#4b12e7d096b255a3b84e53f6831f32e9c7e5fe95"
- integrity sha512-d6lf2IrZJJ7ooVHr7BfwSjRO1yKSJMaiiWYSHcrxSIUtZrCa4KKGwcztdkZ/E9LFleJfjoi1yl+XLR7AX24nbQ==
- dependencies:
- degenerator "^2.2.0"
- ip "^1.1.5"
- netmask "^1.0.6"
-
-package-json@^6.3.0:
- version "6.5.0"
- resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0"
- integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==
- dependencies:
- got "^9.6.0"
- registry-auth-token "^4.0.0"
- registry-url "^5.0.0"
- semver "^6.2.0"
-
-parent-module@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
- integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==
- dependencies:
- callsites "^3.0.0"
-
-parse-json@^2.2.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
- integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=
- dependencies:
- error-ex "^1.2.0"
-
-parse-json@^5.0.0:
- version "5.2.0"
- 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"
- error-ex "^1.3.1"
- json-parse-even-better-errors "^2.3.0"
- lines-and-columns "^1.1.6"
-
-parseurl@~1.3.3:
- version "1.3.3"
- resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
- integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
-
-path-exists@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
- integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=
- dependencies:
- pinkie-promise "^2.0.0"
-
-path-exists@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
- integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
-
-path-is-absolute@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
- integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
-
-path-key@^2.0.0, path-key@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
- integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
-
-path-key@^3.0.0, path-key@^3.1.0:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
- integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
-
-path-parse@^1.0.6:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
- integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
-
-path-to-regexp@0.1.7:
- version "0.1.7"
- resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
- integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=
-
-path-to-regexp@^1.8.0:
- version "1.8.0"
- resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a"
- integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==
- dependencies:
- isarray "0.0.1"
-
-path-type@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
- integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=
- dependencies:
- graceful-fs "^4.1.2"
- pify "^2.0.0"
- pinkie-promise "^2.0.0"
-
-path-type@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
- integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
-
-pend@~1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
- integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA=
-
-performance-now@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
- integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
-
-picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1:
- version "2.2.2"
- resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad"
- integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==
-
-pify@^2.0.0, pify@^2.2.0, pify@^2.3.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
- integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw=
-
-pify@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
- integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=
-
-pify@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
- integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
-
-pinkie-promise@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
- integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o=
- dependencies:
- pinkie "^2.0.0"
-
-pinkie@^2.0.0:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
- integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA=
-
-pkg-dir@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-5.0.0.tgz#a02d6aebe6ba133a928f74aec20bafdfe6b8e760"
- integrity sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==
- dependencies:
- find-up "^5.0.0"
-
-please-upgrade-node@^3.2.0:
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942"
- integrity sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==
- dependencies:
- semver-compare "^1.0.0"
-
-plist@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/plist/-/plist-3.0.1.tgz#a9b931d17c304e8912ef0ba3bdd6182baf2e1f8c"
- integrity sha512-GpgvHHocGRyQm74b6FWEZZVRroHKE1I0/BTjAmySaohK+cUn+hZpbqXkc3KWgW3gQYkqcQej35FohcT0FRlkRQ==
- dependencies:
- base64-js "^1.2.3"
- xmlbuilder "^9.0.7"
- xmldom "0.1.x"
-
-pngquant-bin@^6.0.0:
- version "6.0.0"
- resolved "https://registry.yarnpkg.com/pngquant-bin/-/pngquant-bin-6.0.0.tgz#aff0d7e61095feb96ced379ad8c7294ad3dd1712"
- integrity sha512-oXWAS9MQ9iiDAJRdAZ9KO1mC5UwhzKkJsmetiu0iqIjJuW7JsuLhmc4JdRm7uJkIWRzIAou/Vq2VcjfJwz30Ow==
- dependencies:
- bin-build "^3.0.0"
- bin-wrapper "^4.0.1"
- execa "^4.0.0"
- logalot "^2.0.0"
-
-portfinder@^1.0.23:
- version "1.0.28"
- resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778"
- integrity sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==
- dependencies:
- async "^2.6.2"
- debug "^3.1.1"
- mkdirp "^0.5.5"
-
-prebuild-install@^5.3.4:
- version "5.3.6"
- resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-5.3.6.tgz#7c225568d864c71d89d07f8796042733a3f54291"
- integrity sha512-s8Aai8++QQGi4sSbs/M1Qku62PFK49Jm1CbgXklGz4nmHveDq0wzJkg7Na5QbnO1uNH8K7iqx2EQ/mV0MZEmOg==
- 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.7.0"
- noop-logger "^0.1.1"
- 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"
- which-pm-runs "^1.0.0"
-
-prelude-ls@~1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
- integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=
-
-prepend-http@^1.0.1:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc"
- integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=
-
-prepend-http@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897"
- integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=
-
-prettier@^2.1.1:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.2.1.tgz#795a1a78dd52f073da0cd42b21f9c91381923ff5"
- integrity sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==
-
-pretty-quick@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/pretty-quick/-/pretty-quick-3.1.0.tgz#cb172e9086deb57455dea7c7e8f136cd0a4aef6c"
- integrity sha512-DtxIxksaUWCgPFN7E1ZZk4+Aav3CCuRdhrDSFZENb404sYMtuo9Zka823F+Mgeyt8Zt3bUiCjFzzWYE9LYqkmQ==
- dependencies:
- chalk "^3.0.0"
- execa "^4.0.0"
- find-up "^4.1.0"
- ignore "^5.1.4"
- mri "^1.1.5"
- multimatch "^4.0.0"
-
-process-nextick-args@~1.0.6:
- version "1.0.7"
- resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
- integrity sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=
-
-process-nextick-args@~2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
- integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
-
-progress@^2.0.3:
- version "2.0.3"
- 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.yarnpkg.com/promise-breaker/-/promise-breaker-5.0.0.tgz#58e8541f1619554057da95a211794d7834d30c1d"
- integrity sha512-mgsWQuG4kJ1dtO6e/QlNDLFtMkMzzecsC69aI5hlLEjGHFNpHrvGhFi4LiK5jg2SMQj74/diH+wZliL9LpGsyA==
-
-proto-list@~1.2.1:
- version "1.2.4"
- resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
- integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=
-
-protobufjs@^6.10.2, protobufjs@^6.8.6:
- version "6.10.2"
- resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.10.2.tgz#b9cb6bd8ec8f87514592ba3fdfd28e93f33a469b"
- integrity sha512-27yj+04uF6ya9l+qfpH187aqEzfCF4+Uit0I9ZBQVqK09hk/SQzKa2MUqUpXaVa7LOFRg1TSSr3lVxGOk6c0SQ==
- dependencies:
- "@protobufjs/aspromise" "^1.1.2"
- "@protobufjs/base64" "^1.1.2"
- "@protobufjs/codegen" "^2.0.4"
- "@protobufjs/eventemitter" "^1.1.0"
- "@protobufjs/fetch" "^1.1.0"
- "@protobufjs/float" "^1.0.2"
- "@protobufjs/inquire" "^1.1.0"
- "@protobufjs/path" "^1.1.2"
- "@protobufjs/pool" "^1.1.0"
- "@protobufjs/utf8" "^1.1.0"
- "@types/long" "^4.0.1"
- "@types/node" "^13.7.0"
- long "^4.0.0"
-
-proxy-addr@~2.0.5:
- version "2.0.6"
- resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf"
- integrity sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==
- dependencies:
- forwarded "~0.1.2"
- ipaddr.js "1.9.1"
-
-proxy-agent@^4.0.0:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-4.0.1.tgz#326c3250776c7044cd19655ccbfadf2e065a045c"
- integrity sha512-ODnQnW2jc/FUVwHHuaZEfN5otg/fMbvMxz9nMSUQfJ9JU7q2SZvSULSsjLloVgJOiv9yhc8GlNMKc4GkFmcVEA==
- dependencies:
- agent-base "^6.0.0"
- debug "4"
- http-proxy-agent "^4.0.0"
- https-proxy-agent "^5.0.0"
- lru-cache "^5.1.1"
- pac-proxy-agent "^4.1.0"
- proxy-from-env "^1.0.0"
- socks-proxy-agent "^5.0.0"
-
-proxy-from-env@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
- integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
-
-pseudomap@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
- integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM=
-
-psl@^1.1.28:
- version "1.8.0"
- resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24"
- integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==
-
-pump@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
- integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==
- dependencies:
- end-of-stream "^1.1.0"
- once "^1.3.1"
-
-pumpify@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-2.0.1.tgz#abfc7b5a621307c728b551decbbefb51f0e4aa1e"
- integrity sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw==
- dependencies:
- duplexify "^4.1.1"
- inherits "^2.0.3"
- pump "^3.0.0"
-
-punycode@^1.3.2:
- version "1.4.1"
- resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
- integrity sha1-wNWmOycYgArY4esPpSachN1BhF4=
-
-punycode@^2.1.0, punycode@^2.1.1:
- version "2.1.1"
- 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.yarnpkg.com/pupa/-/pupa-2.1.1.tgz#f5e8fd4afc2c5d97828faa523549ed8744a20d62"
- integrity sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==
- dependencies:
- escape-goat "^2.0.0"
-
-qs@6.7.0:
- version "6.7.0"
- resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
- integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==
-
-qs@^6.6.0:
- version "6.9.6"
- resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.6.tgz#26ed3c8243a431b2924aca84cc90471f35d5a0ee"
- integrity sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==
-
-qs@~6.5.2:
- version "6.5.2"
- resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
- integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
-
-query-string@^5.0.1:
- version "5.1.1"
- resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb"
- integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==
- dependencies:
- decode-uri-component "^0.2.0"
- object-assign "^4.1.0"
- strict-uri-encode "^1.0.0"
-
-range-parser@~1.2.1:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
- integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
-
-raw-body@2.4.0:
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332"
- integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==
- dependencies:
- bytes "3.1.0"
- http-errors "1.7.2"
- iconv-lite "0.4.24"
- unpipe "1.0.0"
-
-raw-body@^2.2.0, raw-body@^2.3.3:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.1.tgz#30ac82f98bb5ae8c152e67149dac8d55153b168c"
- integrity sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==
- dependencies:
- bytes "3.1.0"
- http-errors "1.7.3"
- iconv-lite "0.4.24"
- unpipe "1.0.0"
-
-rc@^1.2.7, rc@^1.2.8:
- version "1.2.8"
- resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
- integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==
- dependencies:
- deep-extend "^0.6.0"
- ini "~1.3.0"
- minimist "^1.2.0"
- strip-json-comments "~2.0.1"
-
-re2@^1.15.8:
- version "1.15.9"
- resolved "https://registry.yarnpkg.com/re2/-/re2-1.15.9.tgz#9ed16171edcb0bc4f0e239bf55229ff3f26acbe3"
- integrity sha512-AXWEhpMTBdC+3oqbjdU07dk0pBCvxh5vbOMLERL6Y8FYBSGn4vXlLe8cYszn64Yy7H8keVMrgPzoSvOd4mePpg==
- dependencies:
- install-artifact-from-github "^1.2.0"
- nan "^2.14.2"
- node-gyp "^7.1.2"
-
-read-pkg-up@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
- integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=
- dependencies:
- find-up "^1.0.0"
- read-pkg "^1.0.0"
-
-read-pkg@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28"
- integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=
- dependencies:
- load-json-file "^1.0.0"
- normalize-package-data "^2.3.2"
- path-type "^1.0.0"
-
-readable-stream@1.1.x:
- version "1.1.14"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9"
- integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk=
- dependencies:
- core-util-is "~1.0.0"
- inherits "~2.0.1"
- isarray "0.0.1"
- string_decoder "~0.10.x"
-
-readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.3.0, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@^2.3.7, readable-stream@~2.3.6:
- version "2.3.7"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
- integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
- dependencies:
- core-util-is "~1.0.0"
- inherits "~2.0.3"
- isarray "~1.0.0"
- process-nextick-args "~2.0.0"
- safe-buffer "~5.1.1"
- string_decoder "~1.1.1"
- util-deprecate "~1.0.1"
-
-readable-stream@^3.1.1, readable-stream@^3.4.0:
- version "3.6.0"
- 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.0:
- version "2.0.6"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e"
- integrity sha1-j5A0HmilPMySh4jaz80Rs265t44=
- dependencies:
- core-util-is "~1.0.0"
- inherits "~2.0.1"
- isarray "~1.0.0"
- process-nextick-args "~1.0.6"
- string_decoder "~0.10.x"
- util-deprecate "~1.0.1"
-
-readdirp@~3.5.0:
- version "3.5.0"
- resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e"
- integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==
- dependencies:
- picomatch "^2.2.1"
-
-redent@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde"
- integrity sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=
- dependencies:
- indent-string "^2.1.0"
- strip-indent "^1.0.1"
-
-redeyed@~2.1.0:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/redeyed/-/redeyed-2.1.1.tgz#8984b5815d99cb220469c99eeeffe38913e6cc0b"
- integrity sha1-iYS1gV2ZyyIEacme7v/jiRPmzAs=
- dependencies:
- esprima "~4.0.0"
-
-registry-auth-token@^4.0.0:
- version "4.2.1"
- resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.1.tgz#6d7b4006441918972ccd5fedcd41dc322c79b250"
- integrity sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==
- dependencies:
- rc "^1.2.8"
-
-registry-url@^5.0.0:
- version "5.1.0"
- 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"
-
-repeating@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda"
- integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=
- dependencies:
- is-finite "^1.0.0"
-
-replace-ext@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.1.tgz#2d6d996d04a15855d967443631dd5f77825b016a"
- integrity sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==
-
-request@^2.87.0, request@^2.88.2:
- version "2.88.2"
- resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
- integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==
- dependencies:
- 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"
-
-resolve-from@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
- integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
-
-resolve@^1.10.0, resolve@^1.3.2:
- version "1.19.0"
- resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c"
- integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==
- dependencies:
- is-core-module "^2.1.0"
- path-parse "^1.0.6"
-
-responselike@1.0.2, responselike@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7"
- integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=
- dependencies:
- lowercase-keys "^1.0.0"
-
-restore-cursor@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
- integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368=
- dependencies:
- onetime "^2.0.0"
- signal-exit "^3.0.2"
-
-retry-request@^4.0.0, retry-request@^4.1.1:
- version "4.1.3"
- resolved "https://registry.yarnpkg.com/retry-request/-/retry-request-4.1.3.tgz#d5f74daf261372cff58d08b0a1979b4d7cab0fde"
- integrity sha512-QnRZUpuPNgX0+D1xVxul6DbJ9slvo4Rm6iV/dn63e048MvGbUZiKySVt6Tenp04JqmchxjiLltGerOJys7kJYQ==
- dependencies:
- debug "^4.1.1"
-
-retry@0.12.0, retry@^0.12.0:
- version "0.12.0"
- resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b"
- integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=
-
-reusify@^1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
- integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
-
-rimraf@2, rimraf@^2.2.8:
- version "2.7.1"
- 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.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
- integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
- dependencies:
- glob "^7.1.3"
-
-router@^1.3.1:
- version "1.3.5"
- resolved "https://registry.yarnpkg.com/router/-/router-1.3.5.tgz#cb2f47f74fd99a77fb3bc01cc947f46b79b1790f"
- integrity sha512-kozCJZUhuSJ5VcLhSb3F8fsmGXy+8HaDbKCAerR1G6tq3mnMZFMuSohbFvGv1c5oMFipijDjRZuuN/Sq5nMf3g==
- dependencies:
- array-flatten "3.0.0"
- debug "2.6.9"
- methods "~1.1.2"
- parseurl "~1.3.3"
- path-to-regexp "0.1.7"
- setprototypeof "1.2.0"
- utils-merge "1.0.1"
-
-rsvp@^4.8.5:
- version "4.8.5"
- resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734"
- integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==
-
-run-async@^2.2.0:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
- integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==
-
-run-parallel@^1.1.9:
- version "1.1.10"
- resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.10.tgz#60a51b2ae836636c81377df16cb107351bcd13ef"
- integrity sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==
-
-rxjs@^6.4.0:
- version "6.6.3"
- resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.3.tgz#8ca84635c4daa900c0d3967a6ee7ac60271ee552"
- integrity sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==
- dependencies:
- tslib "^1.9.0"
-
-safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
- version "5.1.2"
- resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
- integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
-
-safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0:
- version "5.2.1"
- resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
- integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
-
-"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
- integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
-
-seek-bzip@^1.0.5:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.6.tgz#35c4171f55a680916b52a07859ecf3b5857f21c4"
- integrity sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==
- dependencies:
- commander "^2.8.1"
-
-semver-compare@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc"
- integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w=
-
-semver-diff@^3.1.1:
- version "3.1.1"
- 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-regex@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-2.0.0.tgz#a93c2c5844539a770233379107b38c7b4ac9d338"
- integrity sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==
-
-semver-regex@^3.1.2:
- version "3.1.2"
- resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-3.1.2.tgz#34b4c0d361eef262e07199dbef316d0f2ab11807"
- integrity sha512-bXWyL6EAKOJa81XG1OZ/Yyuq+oT0b2YLlxx7c+mrdYPaPbnj6WgVULXhinMIeZGufuUBu/eVRqXEhiv4imfwxA==
-
-semver-truncate@^1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/semver-truncate/-/semver-truncate-1.1.2.tgz#57f41de69707a62709a7e0104ba2117109ea47e8"
- integrity sha1-V/Qd5pcHpicJp+AQS6IRcQnqR+g=
- dependencies:
- semver "^5.3.0"
-
-"semver@2 || 3 || 4 || 5", semver@^5.0.1, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0, semver@^5.7.1:
- version "5.7.1"
- resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
- integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
-
-semver@^6.0.0, semver@^6.2.0, semver@^6.3.0:
- version "6.3.0"
- resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
- integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
-
-semver@^7.0.0, semver@^7.1.3, semver@^7.3.2:
- version "7.3.4"
- resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97"
- integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==
- dependencies:
- lru-cache "^6.0.0"
-
-send@0.17.1:
- version "0.17.1"
- resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8"
- 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"
-
-serve-static@1.14.1:
- version "1.14.1"
- resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9"
- integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==
- dependencies:
- encodeurl "~1.0.2"
- escape-html "~1.0.3"
- parseurl "~1.3.3"
- send "0.17.1"
-
-set-blocking@~2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
- integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
-
-setimmediate@~1.0.4:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
- integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=
-
-setprototypeof@1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683"
- integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==
-
-setprototypeof@1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
- integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==
-
-sharp@^0.25.4:
- version "0.25.4"
- resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.25.4.tgz#1a8e542144a07ab7e9316ab89de80182b827c363"
- integrity sha512-umSzJJ1oBwIOfwFFt/fJ7JgCva9FvrEU2cbbm7u/3hSDZhXvkME8WE5qpaJqLIe2Har5msF5UG4CzYlEg5o3BQ==
- dependencies:
- color "^3.1.2"
- detect-libc "^1.0.3"
- node-addon-api "^3.0.0"
- npmlog "^4.1.2"
- prebuild-install "^5.3.4"
- semver "^7.3.2"
- simple-get "^4.0.0"
- tar "^6.0.2"
- tunnel-agent "^0.6.0"
-
-shebang-command@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
- integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=
- dependencies:
- shebang-regex "^1.0.0"
-
-shebang-command@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
- integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
- dependencies:
- shebang-regex "^3.0.0"
-
-shebang-regex@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
- integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
-
-shebang-regex@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
- integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
-
-signal-exit@^3.0.0, signal-exit@^3.0.2:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
- integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
-
-simple-concat@^1.0.0:
- version "1.0.1"
- 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:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.0.tgz#b45be062435e50d159540b576202ceec40b9c6b3"
- integrity sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==
- dependencies:
- decompress-response "^4.2.0"
- once "^1.3.1"
- simple-concat "^1.0.0"
-
-simple-get@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.0.tgz#73fa628278d21de83dadd5512d2cc1f4872bd675"
- integrity sha512-ZalZGexYr3TA0SwySsr5HlgOOinS4Jsa8YB2GJ6lUNAazyAu4KG/VmzMTwAt2YVXzzVj8QmefmAonZIK2BSGcQ==
- dependencies:
- 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.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a"
- integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=
- dependencies:
- is-arrayish "^0.3.1"
-
-slash@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
- integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
-
-smart-buffer@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.1.0.tgz#91605c25d91652f4661ea69ccf45f1b331ca21ba"
- integrity sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==
-
-snakeize@^0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/snakeize/-/snakeize-0.1.0.tgz#10c088d8b58eb076b3229bb5a04e232ce126422d"
- integrity sha1-EMCI2LWOsHazIpu1oE4jLOEmQi0=
-
-socks-proxy-agent@5, socks-proxy-agent@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-5.0.0.tgz#7c0f364e7b1cf4a7a437e71253bed72e9004be60"
- integrity sha512-lEpa1zsWCChxiynk+lCycKuC502RxDWLKJZoIhnxrWNjLSDGYRFflHA1/228VkRcnv9TIb8w98derGbpKxJRgA==
- dependencies:
- agent-base "6"
- debug "4"
- socks "^2.3.3"
-
-socks@^2.3.3:
- version "2.5.1"
- resolved "https://registry.yarnpkg.com/socks/-/socks-2.5.1.tgz#7720640b6b5ec9a07d556419203baa3f0596df5f"
- integrity sha512-oZCsJJxapULAYJaEYBSzMcz8m3jqgGrHaGhkmU/o/PQfFWYWxkAaA0UMGImb6s6tEXfKi959X6VJjMMQ3P6TTQ==
- dependencies:
- ip "^1.1.5"
- smart-buffer "^4.1.0"
-
-sort-keys-length@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/sort-keys-length/-/sort-keys-length-1.0.1.tgz#9cb6f4f4e9e48155a6aa0671edd336ff1479a188"
- integrity sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg=
- dependencies:
- sort-keys "^1.0.0"
-
-sort-keys@^1.0.0:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad"
- integrity sha1-RBttTTRnmPG05J6JIK37oOVD+a0=
- dependencies:
- is-plain-obj "^1.0.0"
-
-sort-keys@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128"
- integrity sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=
- dependencies:
- is-plain-obj "^1.0.0"
-
-source-map-support@^0.5.17:
- version "0.5.19"
- resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61"
- integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==
- dependencies:
- buffer-from "^1.0.0"
- source-map "^0.6.0"
-
-source-map@^0.6.0, source-map@~0.6.1:
- version "0.6.1"
- resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
- integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
-
-spdx-correct@^3.0.0:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9"
- integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==
- dependencies:
- spdx-expression-parse "^3.0.0"
- spdx-license-ids "^3.0.0"
-
-spdx-exceptions@^2.1.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d"
- integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==
-
-spdx-expression-parse@^3.0.0:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679"
- integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==
- dependencies:
- spdx-exceptions "^2.1.0"
- spdx-license-ids "^3.0.0"
-
-spdx-license-ids@^3.0.0:
- version "3.0.7"
- resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz#e9c18a410e5ed7e12442a549fbd8afa767038d65"
- integrity sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==
-
-sprintf-js@~1.0.2:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
- integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
-
-squeak@^1.0.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/squeak/-/squeak-1.3.0.tgz#33045037b64388b567674b84322a6521073916c3"
- integrity sha1-MwRQN7ZDiLVnZ0uEMiplIQc5FsM=
- dependencies:
- chalk "^1.0.0"
- console-stream "^0.1.1"
- lpad-align "^1.0.1"
-
-sshpk@^1.7.0:
- version "1.16.1"
- resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
- integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==
- dependencies:
- 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"
-
-stack-trace@0.0.x:
- version "0.0.10"
- resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0"
- integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=
-
-"statuses@>= 1.5.0 < 2", statuses@~1.5.0:
- version "1.5.0"
- resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
- integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
-
-stream-events@^1.0.1, stream-events@^1.0.4, stream-events@^1.0.5:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/stream-events/-/stream-events-1.0.5.tgz#bbc898ec4df33a4902d892333d47da9bf1c406d5"
- integrity sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==
- dependencies:
- stubs "^3.0.0"
-
-stream-shift@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d"
- integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==
-
-streamsearch@0.1.2:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a"
- integrity sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=
-
-strict-uri-encode@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
- integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=
-
-string-length@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/string-length/-/string-length-1.0.1.tgz#56970fb1c38558e9e70b728bf3de269ac45adfac"
- integrity sha1-VpcPscOFWOnnC3KL894mmsRa36w=
- dependencies:
- strip-ansi "^3.0.0"
-
-string-width@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
- integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=
- dependencies:
- code-point-at "^1.0.0"
- is-fullwidth-code-point "^1.0.0"
- strip-ansi "^3.0.0"
-
-"string-width@^1.0.2 || 2", string-width@^2.1.0:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
- integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==
- dependencies:
- is-fullwidth-code-point "^2.0.0"
- strip-ansi "^4.0.0"
-
-string-width@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961"
- 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.0"
- resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5"
- integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==
- dependencies:
- emoji-regex "^8.0.0"
- is-fullwidth-code-point "^3.0.0"
- strip-ansi "^6.0.0"
-
-string_decoder@^1.1.1:
- version "1.3.0"
- 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"
-
-string_decoder@~0.10.x:
- version "0.10.31"
- resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
- integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=
-
-string_decoder@~1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
- integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
- dependencies:
- safe-buffer "~5.1.0"
-
-strip-ansi@^3.0.0, strip-ansi@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
- integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=
- dependencies:
- ansi-regex "^2.0.0"
-
-strip-ansi@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
- integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8=
- dependencies:
- ansi-regex "^3.0.0"
-
-strip-ansi@^5.1.0, strip-ansi@^5.2.0:
- version "5.2.0"
- resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae"
- integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==
- dependencies:
- ansi-regex "^4.1.0"
-
-strip-ansi@^6.0.0:
- version "6.0.0"
- resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532"
- integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==
- dependencies:
- ansi-regex "^5.0.0"
-
-strip-bom@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
- integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=
- dependencies:
- is-utf8 "^0.2.0"
-
-strip-dirs@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5"
- integrity sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==
- dependencies:
- is-natural-number "^4.0.1"
-
-strip-eof@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
- integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=
-
-strip-final-newline@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad"
- integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
-
-strip-indent@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2"
- integrity sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=
- dependencies:
- get-stdin "^4.0.1"
-
-strip-json-comments@~2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
- integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
-
-strip-outer@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/strip-outer/-/strip-outer-1.0.1.tgz#b2fd2abf6604b9d1e6013057195df836b8a9d631"
- integrity sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==
- dependencies:
- escape-string-regexp "^1.0.2"
-
-stubs@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/stubs/-/stubs-3.0.0.tgz#e8d2ba1fa9c90570303c030b6900f7d5f89abe5b"
- integrity sha1-6NK6H6nJBXAwPAMLaQD31fiavls=
-
-superstatic@^7.1.0:
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/superstatic/-/superstatic-7.1.0.tgz#42cc773a0f500fb691841e0533d0b8c31f25997f"
- integrity sha512-yBU8iw07nM3Bu4jFc8lnKwLey0cj61OaGmFJZcYC2X+kEpXVmXzERJ3OTAHZAESe1OTeNIuWadt81U5IULGGAA==
- dependencies:
- basic-auth-connect "^1.0.0"
- chalk "^1.1.3"
- compare-semver "^1.0.0"
- compression "^1.7.0"
- connect "^3.6.2"
- destroy "^1.0.4"
- fast-url-parser "^1.1.3"
- fs-extra "^8.1.0"
- glob-slasher "^1.0.1"
- home-dir "^1.0.0"
- is-url "^1.2.2"
- join-path "^1.1.1"
- lodash "^4.17.19"
- mime-types "^2.1.16"
- minimatch "^3.0.4"
- morgan "^1.8.2"
- nash "^3.0.0"
- on-finished "^2.2.0"
- on-headers "^1.0.0"
- path-to-regexp "^1.8.0"
- router "^1.3.1"
- rsvp "^4.8.5"
- string-length "^1.0.0"
- update-notifier "^4.1.1"
- optionalDependencies:
- re2 "^1.15.8"
-
-supports-color@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
- integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=
-
-supports-color@^5.0.0, supports-color@^5.3.0:
- version "5.5.0"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
- integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
- dependencies:
- has-flag "^3.0.0"
-
-supports-color@^7.1.0:
- version "7.2.0"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
- integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
- dependencies:
- has-flag "^4.0.0"
-
-supports-hyperlinks@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-1.0.1.tgz#71daedf36cc1060ac5100c351bb3da48c29c0ef7"
- integrity sha512-HHi5kVSefKaJkGYXbDuKbUGRVxqnWGn3J2e39CYcNJEfWciGq2zYtOhXLTlvrOZW1QU7VX67w7fMmWafHX9Pfw==
- dependencies:
- has-flag "^2.0.0"
- supports-color "^5.0.0"
-
-tar-fs@^2.0.0:
- version "2.1.1"
- 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"
- mkdirp-classic "^0.5.2"
- pump "^3.0.0"
- tar-stream "^2.1.4"
-
-tar-stream@^1.5.2:
- version "1.6.2"
- resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555"
- integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==
- dependencies:
- bl "^1.0.0"
- buffer-alloc "^1.2.0"
- end-of-stream "^1.0.0"
- fs-constants "^1.0.0"
- readable-stream "^2.3.0"
- to-buffer "^1.1.1"
- xtend "^4.0.0"
-
-tar-stream@^2.1.0, tar-stream@^2.1.4:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287"
- 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"
-
-tar@^4.3.0:
- version "4.4.15"
- resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.15.tgz#3caced4f39ebd46ddda4d6203d48493a919697f8"
- integrity sha512-ItbufpujXkry7bHH9NpQyTXPbJ72iTlXgkBAYsAjDXk3Ds8t/3NfO5P4xZGy7u+sYuQUbimgzswX4uQIEeNVOA==
- dependencies:
- chownr "^1.1.1"
- fs-minipass "^1.2.5"
- minipass "^2.8.6"
- minizlib "^1.2.1"
- mkdirp "^0.5.0"
- safe-buffer "^5.1.2"
- yallist "^3.0.3"
-
-tar@^6.0.2:
- version "6.1.0"
- resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.0.tgz#d1724e9bcc04b977b18d5c573b333a2207229a83"
- integrity sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==
- 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"
-
-tcp-port-used@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/tcp-port-used/-/tcp-port-used-1.0.2.tgz#9652b7436eb1f4cfae111c79b558a25769f6faea"
- integrity sha512-l7ar8lLUD3XS1V2lfoJlCBaeoaWo/2xfYt81hM7VlvR4RrMVFqfmzfhLVk40hAb368uitje5gPtBRL1m/DGvLA==
- dependencies:
- debug "4.3.1"
- is2 "^2.0.6"
-
-teeny-request@^7.0.0:
- version "7.0.1"
- resolved "https://registry.yarnpkg.com/teeny-request/-/teeny-request-7.0.1.tgz#bdd41fdffea5f8fbc0d29392cb47bec4f66b2b4c"
- integrity sha512-sasJmQ37klOlplL4Ia/786M5YlOcoLGQyq2TE4WHSRupbAuDaQW0PfVxV4MtdBtRJ4ngzS+1qim8zP6Zp35qCw==
- dependencies:
- http-proxy-agent "^4.0.0"
- https-proxy-agent "^5.0.0"
- node-fetch "^2.6.1"
- stream-events "^1.0.5"
- uuid "^8.0.0"
-
-temp-dir@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d"
- integrity sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=
-
-tempfile@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/tempfile/-/tempfile-2.0.0.tgz#6b0446856a9b1114d1856ffcbe509cccb0977265"
- integrity sha1-awRGhWqbERTRhW/8vlCczLCXcmU=
- dependencies:
- temp-dir "^1.0.0"
- uuid "^3.0.1"
-
-term-size@^2.1.0:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.1.tgz#2a6a54840432c2fb6320fea0f415531e90189f54"
- integrity sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==
-
-text-hex@1.0.x:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5"
- integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==
-
-through2@2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.1.tgz#384e75314d49f32de12eebb8136b8eb6b5d59da9"
- integrity sha1-OE51MU1J8y3hLuu4E2uOtrXVnak=
- dependencies:
- readable-stream "~2.0.0"
- xtend "~4.0.0"
-
-"through@>=2.2.7 <3", through@^2.3.6, through@^2.3.8:
- version "2.3.8"
- resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
- integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
-
-timed-out@^4.0.0, timed-out@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f"
- integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=
-
-timers-ext@^0.1.5, timers-ext@^0.1.7:
- version "0.1.7"
- resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.7.tgz#6f57ad8578e07a3fb9f91d9387d65647555e25c6"
- integrity sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==
- dependencies:
- es5-ext "~0.10.46"
- next-tick "1"
-
-tmp@0.0.33, tmp@^0.0.33:
- version "0.0.33"
- resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
- integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
- dependencies:
- os-tmpdir "~1.0.2"
-
-to-buffer@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80"
- integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==
-
-to-readable-stream@^1.0.0:
- version "1.0.0"
- 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@^5.0.1:
- version "5.0.1"
- 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"
-
-toidentifier@1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
- integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
-
-tough-cookie@~2.5.0:
- version "2.5.0"
- resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
- integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==
- dependencies:
- psl "^1.1.28"
- punycode "^2.1.1"
-
-toxic@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/toxic/-/toxic-1.0.1.tgz#8c2e2528da591100adc3883f2c0e56acfb1c7288"
- integrity sha512-WI3rIGdcaKULYg7KVoB0zcjikqvcYYvcuT6D89bFPz2rVR0Rl0PK6x8/X62rtdLtBKIE985NzVf/auTtGegIIg==
- dependencies:
- lodash "^4.17.10"
-
-"traverse@>=0.3.0 <0.4":
- version "0.3.9"
- resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.3.9.tgz#717b8f220cc0bb7b44e40514c22b2e8bbc70d8b9"
- integrity sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=
-
-trim-newlines@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613"
- integrity sha1-WIeWa7WCpFA6QetST301ARgVphM=
-
-trim-repeated@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/trim-repeated/-/trim-repeated-1.0.0.tgz#e3646a2ea4e891312bf7eace6cfb05380bc01c21"
- integrity sha1-42RqLqTokTEr9+rObPsFOAvAHCE=
- dependencies:
- escape-string-regexp "^1.0.2"
-
-triple-beam@^1.2.0, triple-beam@^1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9"
- integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==
-
-ts-node@^8.6.2:
- version "8.10.2"
- resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.10.2.tgz#eee03764633b1234ddd37f8db9ec10b75ec7fb8d"
- integrity sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==
- dependencies:
- arg "^4.1.0"
- diff "^4.0.1"
- make-error "^1.1.1"
- source-map-support "^0.5.17"
- yn "3.1.1"
-
-tslib@^1.11.1, tslib@^1.13.0, tslib@^1.8.1, tslib@^1.9.0:
- version "1.14.1"
- resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
- integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
-
-tslib@^2.0.0, tslib@^2.0.1:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a"
- integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==
-
-tslint@^6.1.0:
- version "6.1.3"
- resolved "https://registry.yarnpkg.com/tslint/-/tslint-6.1.3.tgz#5c23b2eccc32487d5523bd3a470e9aa31789d904"
- integrity sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==
- dependencies:
- "@babel/code-frame" "^7.0.0"
- builtin-modules "^1.1.1"
- chalk "^2.3.0"
- commander "^2.12.1"
- diff "^4.0.1"
- glob "^7.1.1"
- js-yaml "^3.13.1"
- minimatch "^3.0.4"
- mkdirp "^0.5.3"
- resolve "^1.3.2"
- semver "^5.3.0"
- tslib "^1.13.0"
- tsutils "^2.29.0"
-
-tsutils@^2.29.0:
- version "2.29.0"
- resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99"
- integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==
- dependencies:
- tslib "^1.8.1"
-
-tunnel-agent@^0.6.0:
- version "0.6.0"
- resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
- integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=
- dependencies:
- safe-buffer "^5.0.1"
-
-tweetnacl@^0.14.3, tweetnacl@~0.14.0:
- version "0.14.5"
- resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
- integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
-
-tweetnacl@^1.0.1:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596"
- integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==
-
-tweetsodium@0.0.5:
- version "0.0.5"
- resolved "https://registry.yarnpkg.com/tweetsodium/-/tweetsodium-0.0.5.tgz#f63ab4b1d26d6355d82d512a2bbf03cae96eb3e8"
- integrity sha512-T3aXZtx7KqQbutTtBfn+P5By3HdBuB1eCoGviIrRJV2sXeToxv2X2cv5RvYqgG26PSnN5m3fYixds22Gkfd11w==
- dependencies:
- blakejs "^1.1.0"
- tweetnacl "^1.0.1"
-
-type-check@~0.3.2:
- version "0.3.2"
- resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
- integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=
- dependencies:
- prelude-ls "~1.1.2"
-
-type-fest@^0.11.0:
- version "0.11.0"
- resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1"
- integrity sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==
-
-type-fest@^0.8.1:
- version "0.8.1"
- resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
- integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
-
-type-is@~1.6.17, type-is@~1.6.18:
- version "1.6.18"
- 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"
- mime-types "~2.1.24"
-
-type@^1.0.1:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0"
- integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==
-
-type@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/type/-/type-2.1.0.tgz#9bdc22c648cf8cf86dd23d32336a41cfb6475e3f"
- integrity sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==
-
-typedarray-to-buffer@^3.1.5:
- version "3.1.5"
- resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080"
- integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==
- dependencies:
- is-typedarray "^1.0.0"
-
-typescript@^3.2.2:
- version "3.9.7"
- resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa"
- integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==
-
-unbzip2-stream@^1.0.9:
- version "1.4.3"
- resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz#b0da04c4371311df771cdc215e87f2130991ace7"
- integrity sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==
- dependencies:
- buffer "^5.2.1"
- through "^2.3.8"
-
-unique-string@^2.0.0:
- version "2.0.0"
- 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"
-
-universal-analytics@^0.4.16:
- version "0.4.23"
- resolved "https://registry.yarnpkg.com/universal-analytics/-/universal-analytics-0.4.23.tgz#d915e676850c25c4156762471bdd7cf2eaaca8ac"
- integrity sha512-lgMIH7XBI6OgYn1woDEmxhGdj8yDefMKg7GkWdeATAlQZFrMrNyxSkpDzY57iY0/6fdlzTbBV03OawvvzG+q7A==
- dependencies:
- debug "^4.1.1"
- request "^2.88.2"
- uuid "^3.0.0"
-
-universalify@^0.1.0:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
- integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
-
-unpipe@1.0.0, unpipe@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
- integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=
-
-unzipper@^0.10.10:
- version "0.10.11"
- resolved "https://registry.yarnpkg.com/unzipper/-/unzipper-0.10.11.tgz#0b4991446472cbdb92ee7403909f26c2419c782e"
- integrity sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==
- dependencies:
- big-integer "^1.6.17"
- binary "~0.3.0"
- bluebird "~3.4.1"
- buffer-indexof-polyfill "~1.0.0"
- duplexer2 "~0.1.4"
- fstream "^1.0.12"
- graceful-fs "^4.2.2"
- listenercount "~1.0.1"
- readable-stream "~2.3.6"
- setimmediate "~1.0.4"
-
-update-notifier@^4.1.0, update-notifier@^4.1.1:
- version "4.1.3"
- resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-4.1.3.tgz#be86ee13e8ce48fb50043ff72057b5bd598e1ea3"
- integrity sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A==
- 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"
-
-uri-js@^4.2.2:
- version "4.4.1"
- resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
- integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
- dependencies:
- punycode "^2.1.0"
-
-url-join@0.0.1:
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/url-join/-/url-join-0.0.1.tgz#1db48ad422d3402469a87f7d97bdebfe4fb1e3c8"
- integrity sha1-HbSK1CLTQCRpqH99l73r/k+x48g=
-
-url-parse-lax@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73"
- integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=
- dependencies:
- prepend-http "^1.0.1"
-
-url-parse-lax@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c"
- integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=
- dependencies:
- prepend-http "^2.0.0"
-
-url-to-options@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9"
- integrity sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=
-
-util-deprecate@^1.0.1, util-deprecate@~1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
- integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
-
-utils-merge@1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
- integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
-
-uuid@^3.0.0, uuid@^3.0.1, uuid@^3.3.2:
- version "3.4.0"
- resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
- integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
-
-uuid@^8.0.0:
- version "8.3.2"
- resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
- integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
-
-valid-url@^1:
- version "1.0.9"
- resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200"
- integrity sha1-HBRHm0DxOXp1eC8RXkCGRHQzogA=
-
-validate-npm-package-license@^3.0.1:
- version "3.0.4"
- resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
- integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==
- dependencies:
- spdx-correct "^3.0.0"
- spdx-expression-parse "^3.0.0"
-
-vary@^1, vary@~1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
- integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
-
-verror@1.10.0:
- version "1.10.0"
- resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
- integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=
- dependencies:
- assert-plus "^1.0.0"
- core-util-is "1.0.2"
- extsprintf "^1.2.0"
-
-wcwidth@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8"
- integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=
- dependencies:
- defaults "^1.0.3"
-
-websocket-driver@>=0.5.1:
- version "0.7.4"
- resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760"
- integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==
- dependencies:
- http-parser-js ">=0.5.1"
- safe-buffer ">=5.1.0"
- websocket-extensions ">=0.1.1"
-
-websocket-extensions@>=0.1.1:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42"
- integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==
-
-which-pm-runs@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb"
- integrity sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=
-
-which@^1.2.9:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
- integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
- dependencies:
- isexe "^2.0.0"
-
-which@^2.0.1, which@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
- integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
- dependencies:
- isexe "^2.0.0"
-
-wide-align@^1.1.0:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457"
- integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==
- dependencies:
- string-width "^1.0.2 || 2"
-
-widest-line@^3.1.0:
- version "3.1.0"
- 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"
-
-winston-transport@^4.4.0:
- version "4.4.0"
- resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.4.0.tgz#17af518daa690d5b2ecccaa7acf7b20ca7925e59"
- integrity sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw==
- dependencies:
- readable-stream "^2.3.7"
- triple-beam "^1.2.0"
-
-winston@^3.0.0:
- version "3.3.3"
- resolved "https://registry.yarnpkg.com/winston/-/winston-3.3.3.tgz#ae6172042cafb29786afa3d09c8ff833ab7c9170"
- integrity sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==
- dependencies:
- "@dabh/diagnostics" "^2.0.2"
- async "^3.1.0"
- is-stream "^2.0.0"
- logform "^2.2.0"
- one-time "^1.0.0"
- readable-stream "^3.4.0"
- stack-trace "0.0.x"
- triple-beam "^1.3.0"
- winston-transport "^4.4.0"
-
-word-wrap@~1.2.3:
- version "1.2.3"
- resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
- integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
-
-wrappy@1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
- integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
-
-write-file-atomic@^3.0.0:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8"
- integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==
- dependencies:
- imurmurhash "^0.1.4"
- is-typedarray "^1.0.0"
- signal-exit "^3.0.2"
- typedarray-to-buffer "^3.1.5"
-
-ws@^7.2.3:
- version "7.4.6"
- resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c"
- integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==
-
-xdg-basedir@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13"
- integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==
-
-xmlbuilder@^9.0.7:
- version "9.0.7"
- resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d"
- integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=
-
-xmldom@0.1.x:
- version "0.1.31"
- resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.31.tgz#b76c9a1bd9f0a9737e5a72dc37231cf38375e2ff"
- integrity sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==
-
-xregexp@2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943"
- integrity sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=
-
-xtend@^4.0.0, xtend@~4.0.0:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
- integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
-
-yallist@^2.1.2:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
- integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=
-
-yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
- integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
-
-yallist@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
- integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
-
-yaml@^1.10.0:
- version "1.10.0"
- resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e"
- integrity sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==
-
-yauzl@^2.4.2:
- version "2.10.0"
- resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"
- integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=
- dependencies:
- buffer-crc32 "~0.2.3"
- fd-slicer "~1.1.0"
-
-yn@3.1.1:
- version "3.1.1"
- 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==
-
-zip-stream@^2.1.2:
- version "2.1.3"
- resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-2.1.3.tgz#26cc4bdb93641a8590dd07112e1f77af1758865b"
- integrity sha512-EkXc2JGcKhO5N5aZ7TmuNo45budRaFGHOmz24wtJR7znbNqDPmdZtUauKX6et8KAVseAMBOyWJqEpXcHTBsh7Q==
- dependencies:
- archiver-utils "^2.1.0"
- compress-commons "^2.1.1"
- readable-stream "^3.4.0"
diff --git a/cloudbuild.yaml b/cloudbuild.yaml
index 0a3df0fae..75714cd4d 100644
--- a/cloudbuild.yaml
+++ b/cloudbuild.yaml
@@ -1,42 +1,37 @@
steps:
- - name: node:10.17.0
- entrypoint: yarn
- args: ["install"]
- dir: "www"
- - name: node:10.17.0
- entrypoint: yarn
- args:
- - env
- - "${_PROJECT_ID}"
- - "${_FIREBASE_WEB_API_KEY}"
- - "${_ALGOLIA_APP_ID}"
- - "${_ALGOLIA_APP_KEY}"
- dir: "www"
- - name: node:10.17.0
- entrypoint: yarn
- args: ["build"]
- dir: "www"
- - name: node:10.17.0
- entrypoint: yarn
- args:
- - "target"
- - "${_HOSTING_TARGET}"
- - --project
- - "${_PROJECT_ID}"
- dir: "www"
- - name: node:10.17.0
- entrypoint: yarn
- args:
- - deploy
- - --project
- - "${_PROJECT_ID}"
- - --debug
- - --token
- - "${_FIREBASE_TOKEN}"
- - --only
- - hosting
- dir: "www"
+ - name: node:10.17.0
+ entrypoint: yarn
+ args: ["install"]
+ - name: node:10.17.0
+ entrypoint: yarn
+ args:
+ - env
+ - "${_PROJECT_ID}"
+ - "${_FIREBASE_WEB_API_KEY}"
+ - "${_ALGOLIA_APP_ID}"
+ - "${_ALGOLIA_APP_KEY}"
+ - name: node:10.17.0
+ entrypoint: yarn
+ args: ["build"]
+ - name: node:10.17.0
+ entrypoint: yarn
+ args:
+ - "target"
+ - "${_HOSTING_TARGET}"
+ - --project
+ - "${_PROJECT_ID}"
+ - name: node:10.17.0
+ entrypoint: yarn
+ args:
+ - deploy
+ - --project
+ - "${_PROJECT_ID}"
+ - --debug
+ - --token
+ - "${_FIREBASE_TOKEN}"
+ - --only
+ - hosting
substitutions:
- _PROJECT_ID: "project-id" # default value
+ _PROJECT_ID: "project-id" # default value
options:
- machineType: "N1_HIGHCPU_8"
+ machineType: "N1_HIGHCPU_8"
diff --git a/cloudbuildfunctions.yaml b/cloudbuildfunctions.yaml
deleted file mode 100644
index e0ad31419..000000000
--- a/cloudbuildfunctions.yaml
+++ /dev/null
@@ -1,47 +0,0 @@
-steps:
- # - name: "gcr.io/kaniko-project/executor:latest"
- # args:
- # - --destination=gcr.io/$PROJECT_ID/image
- # - --cache=true
- # - --cache-ttl=24h
- - name: node:10.15.1
- entrypoint: yarn
- args: ["install"]
- dir: "cloud_functions/functions"
- - name: node:10.15.1
- entrypoint: yarn
- args:
- - "generateConfig"
- - "${_FUNCTIONS_GROUP}"
- - "${_FUNCTION_CONFIG}"
- dir: "cloud_functions/functions"
- - name: node:10.15.1
- entrypoint: yarn
- args:
- - "deployFT"
- - "--project"
- - "${_PROJECT_ID}"
- - "--token"
- - "${_FIREBASE_TOKEN}"
- - "--only"
- - "functions:${_FUNCTIONS_GROUP}"
- dir: "cloud_functions/functions"
- # - name: gcr.io/cloud-builders/gcloud
- # args:
- # - functions
- # - deploy
- # - "${_FUNCTIONS_GROUP}"
- # dir: "cloud_functions/functions"
- - name: node:10.15.1
- entrypoint: yarn
- args:
- - "updateStatus"
- - "${_REQUEST_DOC_PATH}"
- - "${_FUNCTION_CONFIG}"
- dir: "cloud_functions/functions"
-
-substitutions:
- _PROJECT_ID: "project-id" # default value
- _FUNCTIONS_GROUP: "exportTable" # default value
-options:
- machineType: "N1_HIGHCPU_8"
diff --git a/craco.config.js b/craco.config.js
new file mode 100644
index 000000000..247de392c
--- /dev/null
+++ b/craco.config.js
@@ -0,0 +1,21 @@
+const CracoSwcPlugin = require("craco-swc");
+
+module.exports = {
+ plugins: [
+ {
+ plugin: CracoSwcPlugin,
+ options: {
+ swcLoaderOptions: {
+ jsc: {
+ target: "es2019",
+ transform: {
+ react: {
+ runtime: "automatic",
+ },
+ },
+ },
+ },
+ },
+ },
+ ],
+};
diff --git a/www/createDotEnv.js b/createDotEnv.js
similarity index 61%
rename from www/createDotEnv.js
rename to createDotEnv.js
index 623ddb7f3..e38b9c761 100644
--- a/www/createDotEnv.js
+++ b/createDotEnv.js
@@ -1,18 +1,18 @@
const fs = require("fs");
const main = (
- projectID = "",
- firebaseWebApiKey = "",
- algoliaAppId = "",
- algoliaSearhApiKey = ""
+ projectID = "",
+ firebaseWebApiKey = "",
+ algoliaAppId = "",
+ algoliaSearhApiKey = ""
) => {
- return fs.writeFileSync(
- ".env",
- `REACT_APP_FIREBASE_PROJECT_ID = ${projectID}
+ return fs.writeFileSync(
+ ".env",
+ `REACT_APP_FIREBASE_PROJECT_ID = ${projectID}
REACT_APP_FIREBASE_PROJECT_WEB_API_KEY = ${firebaseWebApiKey}
REACT_APP_ALGOLIA_APP_ID = ${algoliaAppId}
REACT_APP_ALGOLIA_SEARCH_API_KEY = ${algoliaSearhApiKey}`
- );
+ );
};
main(process.argv[2], process.argv[3], process.argv[4], process.argv[5]);
diff --git a/e2e/.gitignore b/e2e/.gitignore
deleted file mode 100644
index 7f7abc4e6..000000000
--- a/e2e/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-firebase-credentials.json
\ No newline at end of file
diff --git a/e2e/auth.ts b/e2e/auth.ts
deleted file mode 100644
index 1fe33eb4c..000000000
--- a/e2e/auth.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import { auth } from "./credentials";
-
-export const authenticateUser = async (page, email = "shams@antler.co") => {
- const user = await auth.getUserByEmail(email);
- const jwt = await auth.createCustomToken(user.uid);
- // Go to http://localhost:3000/jwtAuth
- await page.goto("http://localhost:3000/jwtAuth");
-
- // Click input[name="JWT"]
- await page.click('input[name="JWT"]');
-
- // Fill input[name="JWT"]
- await page.fill('input[name="JWT"]', jwt);
-
- // Click text="Sign in"
- return await Promise.all([
- page.waitForNavigation(/*{ url: 'http://localhost:3000/' }*/),
- page.click('text="Sign in"'),
- ]);
-};
diff --git a/e2e/credentials.ts b/e2e/credentials.ts
deleted file mode 100644
index 0a0acead3..000000000
--- a/e2e/credentials.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-// Initialize Firebase Admin
-import * as admin from "firebase-admin";
-// Initialize Firebase Admin
-const serverTimestamp = admin.firestore.FieldValue.serverTimestamp;
-const serviceAccount = require("./firebase-credentials.json");
-
-admin.initializeApp({
- credential: admin.credential.cert(serviceAccount),
- databaseURL: `https://${serviceAccount.project_id}.firebaseio.com`,
-});
-export const db = admin.firestore();
-export const auth = admin.auth();
diff --git a/e2e/index.ts b/e2e/index.ts
deleted file mode 100644
index dcdb26144..000000000
--- a/e2e/index.ts
+++ /dev/null
@@ -1,123 +0,0 @@
-import { chromium } from "playwright";
-import { authenticateUser } from "./auth";
-(async () => {
- const browser = await chromium.launch({
- headless: false,
- });
- const context = await browser.newContext();
-
- // Open new page
- const page = await context.newPage();
-
- await authenticateUser(page);
-
- await page.goto("http://localhost:3000/table/test");
- // Click text="Add Column"
- await page.click(
- "//div[starts-with(normalize-space(.), 'EdwardKnightEd has had a multi decade career in European banking and capital mar') and normalize-space(@role)='row']/div[2][normalize-space(@role)='gridcell']/div/div/div/div[normalize-space(@role)='button']"
- );
-
- // Click //li[normalize-space(.)='LON3' and normalize-space(@role)='option']/*[local-name()="svg"]
- await page.click(
- "//li[normalize-space(.)='LON3' and normalize-space(@role)='option']/*[local-name()=\"svg\"]"
- );
-
- // Click //div[normalize-space(.)='Beijing' and normalize-space(@role)='button']
- await page.click(
- "//div[normalize-space(.)='Beijing' and normalize-space(@role)='button']"
- );
-
- // Click //li[normalize-space(.)='India' and normalize-space(@role)='option']/*[local-name()="svg"]
- await page.click(
- "//li[normalize-space(.)='India' and normalize-space(@role)='option']/*[local-name()=\"svg\"]"
- );
-
- // Click //li[normalize-space(.)='Oslo' and normalize-space(@role)='option']
- await page.click(
- "//li[normalize-space(.)='Oslo' and normalize-space(@role)='option']"
- );
-
- // Click text="Add Row"
- await page.click('text="Add Row"');
-
- // Click //button[normalize-space(.)='Hide']
- await page.click("//button[normalize-space(.)='Hide']");
-
- // Click li[role="option"] >> text="Department"
- await page.click('li[role="option"] >> text="Department"');
-
- // Click li[role="option"] >> text="Location"
- await page.click('li[role="option"] >> text="Location"');
-
- // Click li[role="option"] >> text="Designation"
- await page.click('li[role="option"] >> text="Designation"');
-
- // Click li[role="option"] >> text="Employment Type"
- await page.click('li[role="option"] >> text="Employment Type"');
-
- // Click text="Done"
- await page.click('text="Done"');
-
- // Click .MuiGrid-root.MuiGrid-item .MuiGrid-root .MuiButtonBase-root .MuiButton-label .MuiButton-startIcon .MuiSvgIcon-root path
- await page.click(
- ".MuiGrid-root.MuiGrid-item .MuiGrid-root .MuiButtonBase-root .MuiButton-label .MuiButton-startIcon .MuiSvgIcon-root path"
- );
-
- // Click //div[normalize-space(.)='Select Column']
- await page.click("//div[normalize-space(.)='Select Column']");
-
- // Click //li[normalize-space(.)='Last Name' and normalize-space(@role)='option']
- await page.click(
- "//li[normalize-space(.)='Last Name' and normalize-space(@role)='option']"
- );
-
- // Click div[role="presentation"] div[role="button"]
- await page.click('div[role="presentation"] div[role="button"]');
-
- // Click //li[normalize-space(.)='Employment Type' and normalize-space(@role)='option']
- await page.click(
- "//li[normalize-space(.)='Employment Type' and normalize-space(@role)='option']"
- );
-
- // Click //div[normalize-space(.)='Select Condition' and normalize-space(@role)='button']
- await page.click(
- "//div[normalize-space(.)='Select Condition' and normalize-space(@role)='button']"
- );
-
- // Click //li[normalize-space(.)='Equals' and normalize-space(@role)='option']
- await page.click(
- "//li[normalize-space(.)='Equals' and normalize-space(@role)='option']"
- );
-
- // Click //div[normalize-space(.)='Equals' and normalize-space(@role)='button']
- await page.click(
- "//div[normalize-space(.)='Equals' and normalize-space(@role)='button']"
- );
-
- // Click //div[normalize-space(.)='Select ConditionEqualsmatches any of' and normalize-space(@role)='presentation']/div[1]
- await page.click(
- "//div[normalize-space(.)='Select ConditionEqualsmatches any of' and normalize-space(@role)='presentation']/div[1]"
- );
-
- // Click //div[normalize-space(.)='' and normalize-space(@role)='button']
- await page.click(
- "//div[normalize-space(.)='' and normalize-space(@role)='button']"
- );
-
- // Click //li[normalize-space(.)='Part Time' and normalize-space(@role)='option']/*[local-name()="svg"]
- await page.click(
- "//li[normalize-space(.)='Part Time' and normalize-space(@role)='option']/*[local-name()=\"svg\"]"
- );
-
- // Click text="Apply"
- await page.click('text="Apply"');
-
- // Click //div[normalize-space(.)='employmentType == Part Time' and normalize-space(@role)='button']/*[local-name()="svg"]
- await page.click(
- "//div[normalize-space(.)='employmentType == Part Time' and normalize-space(@role)='button']/*[local-name()=\"svg\"]"
- );
-
- // ---------------------
- await context.close();
- await browser.close();
-})();
diff --git a/e2e/package.json b/e2e/package.json
deleted file mode 100644
index 63a855c25..000000000
--- a/e2e/package.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "devDependencies": {
- "@types/node": "^14.14.33",
- "playwright": "^1.9.2",
- "playwright-cli": "^0.180.0"
- },
- "dependencies": {
- "firebase-admin": "^9.5.0"
- }
-}
diff --git a/e2e/yarn.lock b/e2e/yarn.lock
deleted file mode 100644
index 1c594e953..000000000
--- a/e2e/yarn.lock
+++ /dev/null
@@ -1,1196 +0,0 @@
-# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
-# yarn lockfile v1
-
-
-"@firebase/app-types@0.6.1":
- version "0.6.1"
- resolved "https://registry.yarnpkg.com/@firebase/app-types/-/app-types-0.6.1.tgz#dcbd23030a71c0c74fc95d4a3f75ba81653850e9"
- integrity sha512-L/ZnJRAq7F++utfuoTKX4CLBG5YR7tFO3PLzG1/oXXKEezJ0kRL3CMRoueBEmTCzVb/6SIs2Qlaw++uDgi5Xyg==
-
-"@firebase/auth-interop-types@0.1.5":
- version "0.1.5"
- resolved "https://registry.yarnpkg.com/@firebase/auth-interop-types/-/auth-interop-types-0.1.5.tgz#9fc9bd7c879f16b8d1bb08373a0f48c3a8b74557"
- integrity sha512-88h74TMQ6wXChPA6h9Q3E1Jg6TkTHep2+k63OWg3s0ozyGVMeY+TTOti7PFPzq5RhszQPQOoCi59es4MaRvgCw==
-
-"@firebase/component@0.1.21":
- version "0.1.21"
- resolved "https://registry.yarnpkg.com/@firebase/component/-/component-0.1.21.tgz#56062eb0d449dc1e7bbef3c084a9b5fa48c7c14d"
- integrity sha512-kd5sVmCLB95EK81Pj+yDTea8pzN2qo/1yr0ua9yVi6UgMzm6zAeih73iVUkaat96MAHy26yosMufkvd3zC4IKg==
- dependencies:
- "@firebase/util" "0.3.4"
- tslib "^1.11.1"
-
-"@firebase/database-types@0.6.1", "@firebase/database-types@^0.6.1":
- version "0.6.1"
- resolved "https://registry.yarnpkg.com/@firebase/database-types/-/database-types-0.6.1.tgz#cf1cfc03e617ed4c2561703781f85ba4c707ff65"
- integrity sha512-JtL3FUbWG+bM59iYuphfx9WOu2Mzf0OZNaqWiQ7lJR8wBe7bS9rIm9jlBFtksB7xcya1lZSQPA/GAy2jIlMIkA==
- dependencies:
- "@firebase/app-types" "0.6.1"
-
-"@firebase/database@^0.8.1":
- version "0.8.3"
- resolved "https://registry.yarnpkg.com/@firebase/database/-/database-0.8.3.tgz#4e5efa8fc8df00d6febfd9c8d6d6e409596659f7"
- integrity sha512-i29rr3kcPltIkA8La9M1lgsSxx9bfu5lCQ0T+tbJptZ3UpqpcL1NzCcZa24cJjiLgq3HQNPyLvUvCtcPSFDlRg==
- dependencies:
- "@firebase/auth-interop-types" "0.1.5"
- "@firebase/component" "0.1.21"
- "@firebase/database-types" "0.6.1"
- "@firebase/logger" "0.2.6"
- "@firebase/util" "0.3.4"
- faye-websocket "0.11.3"
- tslib "^1.11.1"
-
-"@firebase/logger@0.2.6":
- version "0.2.6"
- resolved "https://registry.yarnpkg.com/@firebase/logger/-/logger-0.2.6.tgz#3aa2ca4fe10327cabf7808bd3994e88db26d7989"
- integrity sha512-KIxcUvW/cRGWlzK9Vd2KB864HlUnCfdTH0taHE0sXW5Xl7+W68suaeau1oKNEqmc3l45azkd4NzXTCWZRZdXrw==
-
-"@firebase/util@0.3.4":
- version "0.3.4"
- resolved "https://registry.yarnpkg.com/@firebase/util/-/util-0.3.4.tgz#e389d0e0e2aac88a5235b06ba9431db999d4892b"
- integrity sha512-VwjJUE2Vgr2UMfH63ZtIX9Hd7x+6gayi6RUXaTqEYxSbf/JmehLmAEYSuxS/NckfzAXWeGnKclvnXVibDgpjQQ==
- dependencies:
- tslib "^1.11.1"
-
-"@google-cloud/common@^3.3.0":
- version "3.4.1"
- resolved "https://registry.yarnpkg.com/@google-cloud/common/-/common-3.4.1.tgz#a1920d73c38437923b4b134e245c392d36c442e9"
- integrity sha512-e5z0CwsM0RXky+PnyPtQ3QK46ksqm+kE7kX8pm8X+ddBwZJipHchKeazMM5fLlGCS+AALalzXb+uYmH72TRnpQ==
- dependencies:
- "@google-cloud/projectify" "^2.0.0"
- "@google-cloud/promisify" "^2.0.0"
- arrify "^2.0.1"
- duplexify "^4.1.1"
- ent "^2.2.0"
- extend "^3.0.2"
- google-auth-library "^6.1.1"
- retry-request "^4.1.1"
- teeny-request "^7.0.0"
-
-"@google-cloud/firestore@^4.5.0":
- version "4.9.7"
- resolved "https://registry.yarnpkg.com/@google-cloud/firestore/-/firestore-4.9.7.tgz#8fb9080ba0f6e074013412835b60db926515d139"
- integrity sha512-s5W6rRxD5y3Oe3KJUNztIy4eIi9dBwJU36jd/QM3L8frpCuSh1fn6z0BD8IAV0AirQAg6aOzSlcwAwd/yeXCkw==
- dependencies:
- fast-deep-equal "^3.1.1"
- functional-red-black-tree "^1.0.1"
- google-gax "^2.9.2"
- protobufjs "^6.8.6"
-
-"@google-cloud/paginator@^3.0.0":
- version "3.0.5"
- resolved "https://registry.yarnpkg.com/@google-cloud/paginator/-/paginator-3.0.5.tgz#9d6b96c421a89bd560c1bc2c197c7611ef21db6c"
- integrity sha512-N4Uk4BT1YuskfRhKXBs0n9Lg2YTROZc6IMpkO/8DIHODtm5s3xY8K5vVBo23v/2XulY3azwITQlYWgT4GdLsUw==
- dependencies:
- arrify "^2.0.0"
- extend "^3.0.2"
-
-"@google-cloud/projectify@^2.0.0":
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/@google-cloud/projectify/-/projectify-2.0.1.tgz#13350ee609346435c795bbfe133a08dfeab78d65"
- integrity sha512-ZDG38U/Yy6Zr21LaR3BTiiLtpJl6RkPS/JwoRT453G+6Q1DhlV0waNf8Lfu+YVYGIIxgKnLayJRfYlFJfiI8iQ==
-
-"@google-cloud/promisify@^2.0.0":
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/@google-cloud/promisify/-/promisify-2.0.3.tgz#f934b5cdc939e3c7039ff62b9caaf59a9d89e3a8"
- integrity sha512-d4VSA86eL/AFTe5xtyZX+ePUjE8dIFu2T8zmdeNBSa5/kNgXPCx/o/wbFNHAGLJdGnk1vddRuMESD9HbOC8irw==
-
-"@google-cloud/storage@^5.3.0":
- version "5.3.0"
- resolved "https://registry.yarnpkg.com/@google-cloud/storage/-/storage-5.3.0.tgz#cf86683911cce68829e46de544abb41947d29da2"
- integrity sha512-3t5UF3SZ14Bw2kcBHubCai6EIugU2GnQOstYWVSFuoO8IJ94RAaIOPq/dtexvQbUTpBTAGpd5smVR9WPL1mJVw==
- dependencies:
- "@google-cloud/common" "^3.3.0"
- "@google-cloud/paginator" "^3.0.0"
- "@google-cloud/promisify" "^2.0.0"
- arrify "^2.0.0"
- compressible "^2.0.12"
- concat-stream "^2.0.0"
- date-and-time "^0.14.2"
- duplexify "^3.5.0"
- extend "^3.0.2"
- gaxios "^3.0.0"
- gcs-resumable-upload "^3.1.0"
- hash-stream-validation "^0.2.2"
- mime "^2.2.0"
- mime-types "^2.0.8"
- onetime "^5.1.0"
- p-limit "^3.0.1"
- pumpify "^2.0.0"
- snakeize "^0.1.0"
- stream-events "^1.0.1"
- xdg-basedir "^4.0.0"
-
-"@grpc/grpc-js@~1.2.0":
- version "1.2.10"
- resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.2.10.tgz#f316d29a45fcc324e923d593cb849d292b1ed598"
- integrity sha512-wj6GkNiorWYaPiIZ767xImmw7avMMVUweTvPFg4mJWOxz2180DKwfuxhJJZ7rpc1+7D3mX/v8vJdxTuIo71Ieg==
- dependencies:
- "@types/node" ">=12.12.47"
- google-auth-library "^6.1.1"
- semver "^6.2.0"
-
-"@grpc/proto-loader@^0.5.1":
- version "0.5.5"
- resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.5.5.tgz#6725e7a1827bdf8e92e29fbf4e9ef0203c0906a9"
- integrity sha512-WwN9jVNdHRQoOBo9FDH7qU+mgfjPc8GygPYms3M+y3fbQLfnCe/Kv/E01t7JRgnrsOHH8euvSbed3mIalXhwqQ==
- dependencies:
- lodash.camelcase "^4.3.0"
- protobufjs "^6.8.6"
-
-"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2":
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf"
- integrity sha1-m4sMxmPWaafY9vXQiToU00jzD78=
-
-"@protobufjs/base64@^1.1.2":
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735"
- integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==
-
-"@protobufjs/codegen@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb"
- integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==
-
-"@protobufjs/eventemitter@^1.1.0":
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70"
- integrity sha1-NVy8mLr61ZePntCV85diHx0Ga3A=
-
-"@protobufjs/fetch@^1.1.0":
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45"
- integrity sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=
- dependencies:
- "@protobufjs/aspromise" "^1.1.1"
- "@protobufjs/inquire" "^1.1.0"
-
-"@protobufjs/float@^1.0.2":
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1"
- integrity sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=
-
-"@protobufjs/inquire@^1.1.0":
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089"
- integrity sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=
-
-"@protobufjs/path@^1.1.2":
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d"
- integrity sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=
-
-"@protobufjs/pool@^1.1.0":
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54"
- integrity sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=
-
-"@protobufjs/utf8@^1.1.0":
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
- integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=
-
-"@tootallnate/once@1":
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
- integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==
-
-"@types/long@^4.0.0", "@types/long@^4.0.1":
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9"
- integrity sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==
-
-"@types/node@*", "@types/node@>=12.12.47", "@types/node@^14.14.33":
- version "14.14.33"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.33.tgz#9e4f8c64345522e4e8ce77b334a8aaa64e2b6c78"
- integrity sha512-oJqcTrgPUF29oUP8AsUqbXGJNuPutsetaa9kTQAQce5Lx5dTYWV02ScBiT/k1BX/Z7pKeqedmvp39Wu4zR7N7g==
-
-"@types/node@^10.10.0":
- version "10.17.44"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.44.tgz#3945e6b702cb6403f22b779c8ea9e5c3f44ead40"
- integrity sha512-vHPAyBX1ffLcy4fQHmDyIUMUb42gHZjPHU66nhvbMzAWJqHnySGZ6STwN3rwrnSd1FHB0DI/RWgGELgKSYRDmw==
-
-"@types/node@^13.7.0":
- version "13.13.30"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.30.tgz#1ed6e01e4ca576d5aec9cc802cc3bcf94c274192"
- integrity sha512-HmqFpNzp3TSELxU/bUuRK+xzarVOAsR00hzcvM0TXrMlt/+wcSLa5q6YhTb6/cA6wqDCZLDcfd8fSL95x5h7AA==
-
-"@types/yauzl@^2.9.1":
- version "2.9.1"
- resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.9.1.tgz#d10f69f9f522eef3cf98e30afb684a1e1ec923af"
- integrity sha512-A1b8SU4D10uoPjwb0lnHmmu8wZhR9d+9o2PKBQT2jU5YPTKsxac6M2qGAdY7VcL+dHHhARVUDmeg0rOrcd9EjA==
- dependencies:
- "@types/node" "*"
-
-abort-controller@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
- integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==
- dependencies:
- event-target-shim "^5.0.0"
-
-agent-base@6:
- version "6.0.2"
- resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
- integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
- dependencies:
- debug "4"
-
-arrify@^2.0.0, arrify@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa"
- integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==
-
-balanced-match@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
- integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
-
-base64-js@^1.3.0:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1"
- integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==
-
-bignumber.js@^9.0.0:
- version "9.0.1"
- resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.1.tgz#8d7ba124c882bfd8e43260c67475518d0689e4e5"
- integrity sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==
-
-brace-expansion@^1.1.7:
- version "1.1.11"
- resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
- integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
- dependencies:
- balanced-match "^1.0.0"
- concat-map "0.0.1"
-
-buffer-crc32@~0.2.3:
- version "0.2.13"
- resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
- integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=
-
-buffer-equal-constant-time@1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
- integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=
-
-buffer-from@^1.0.0:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
- integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
-
-commander@^6.1.0:
- version "6.2.1"
- resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c"
- integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==
-
-compressible@^2.0.12:
- version "2.0.18"
- resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba"
- integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==
- dependencies:
- mime-db ">= 1.43.0 < 2"
-
-concat-map@0.0.1:
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
- integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
-
-concat-stream@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-2.0.0.tgz#414cf5af790a48c60ab9be4527d56d5e41133cb1"
- integrity sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==
- dependencies:
- buffer-from "^1.0.0"
- inherits "^2.0.3"
- readable-stream "^3.0.2"
- typedarray "^0.0.6"
-
-configstore@^5.0.0:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96"
- integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==
- 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"
-
-core-util-is@~1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
- integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
-
-crypto-random-string@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5"
- integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==
-
-date-and-time@^0.14.2:
- version "0.14.2"
- resolved "https://registry.yarnpkg.com/date-and-time/-/date-and-time-0.14.2.tgz#a4266c3dead460f6c231fe9674e585908dac354e"
- integrity sha512-EFTCh9zRSEpGPmJaexg7HTuzZHh6cnJj1ui7IGCFNXzd2QdpsNh05Db5TF3xzJm30YN+A8/6xHSuRcQqoc3kFA==
-
-debug@4, debug@^4.1.1:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1"
- integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==
- dependencies:
- ms "2.1.2"
-
-dicer@^0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/dicer/-/dicer-0.3.0.tgz#eacd98b3bfbf92e8ab5c2fdb71aaac44bb06b872"
- integrity sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA==
- dependencies:
- streamsearch "0.1.2"
-
-dot-prop@^5.2.0:
- version "5.3.0"
- resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88"
- integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==
- dependencies:
- is-obj "^2.0.0"
-
-duplexify@^3.5.0:
- version "3.7.1"
- resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309"
- integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==
- dependencies:
- end-of-stream "^1.0.0"
- inherits "^2.0.1"
- readable-stream "^2.0.0"
- stream-shift "^1.0.0"
-
-duplexify@^4.0.0, duplexify@^4.1.1:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.1.tgz#7027dc374f157b122a8ae08c2d3ea4d2d953aa61"
- integrity sha512-DY3xVEmVHTv1wSzKNbwoU6nVjzI369Y6sPoqfYr0/xlx3IdX2n94xIszTcjPO8W8ZIv0Wb0PXNcjuZyT4wiICA==
- dependencies:
- end-of-stream "^1.4.1"
- inherits "^2.0.3"
- readable-stream "^3.1.1"
- stream-shift "^1.0.0"
-
-ecdsa-sig-formatter@1.0.11, ecdsa-sig-formatter@^1.0.11:
- version "1.0.11"
- 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"
-
-end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1:
- version "1.4.4"
- resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
- integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
- dependencies:
- once "^1.4.0"
-
-ent@^2.2.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d"
- integrity sha1-6WQhkyWiHQX0RGai9obtbOX13R0=
-
-escape-string-regexp@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344"
- integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==
-
-event-target-shim@^5.0.0:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789"
- integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==
-
-extend@^3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
- integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
-
-extract-zip@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a"
- integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==
- dependencies:
- debug "^4.1.1"
- get-stream "^5.1.0"
- yauzl "^2.10.0"
- optionalDependencies:
- "@types/yauzl" "^2.9.1"
-
-fast-deep-equal@^3.1.1:
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
- integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
-
-fast-text-encoding@^1.0.0, fast-text-encoding@^1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz#ec02ac8e01ab8a319af182dae2681213cfe9ce53"
- integrity sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig==
-
-faye-websocket@0.11.3:
- version "0.11.3"
- resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.3.tgz#5c0e9a8968e8912c286639fde977a8b209f2508e"
- integrity sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==
- dependencies:
- websocket-driver ">=0.5.1"
-
-fd-slicer@~1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e"
- integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=
- dependencies:
- pend "~1.2.0"
-
-firebase-admin@^9.5.0:
- version "9.5.0"
- resolved "https://registry.yarnpkg.com/firebase-admin/-/firebase-admin-9.5.0.tgz#438bc343f1fa0644c2bdbeb36eefec3eda3bf966"
- integrity sha512-OPXFOTDcAE+NORpfhq7YMEDk+vFClBtjfpkrjm2JHRxb8DpMm+K3AcusonFPU/WOH4FhiVN9JHB0+NPE20S3gQ==
- dependencies:
- "@firebase/database" "^0.8.1"
- "@firebase/database-types" "^0.6.1"
- "@types/node" "^10.10.0"
- dicer "^0.3.0"
- jsonwebtoken "^8.5.1"
- node-forge "^0.10.0"
- optionalDependencies:
- "@google-cloud/firestore" "^4.5.0"
- "@google-cloud/storage" "^5.3.0"
-
-fs.realpath@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
- integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
-
-functional-red-black-tree@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
- integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=
-
-gaxios@^3.0.0:
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/gaxios/-/gaxios-3.2.0.tgz#11b6f0e8fb08d94a10d4d58b044ad3bec6dd486a"
- integrity sha512-+6WPeVzPvOshftpxJwRi2Ozez80tn/hdtOUag7+gajDHRJvAblKxTFSSMPtr2hmnLy7p0mvYz0rMXLBl8pSO7Q==
- dependencies:
- abort-controller "^3.0.0"
- extend "^3.0.2"
- https-proxy-agent "^5.0.0"
- is-stream "^2.0.0"
- node-fetch "^2.3.0"
-
-gaxios@^4.0.0:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/gaxios/-/gaxios-4.0.1.tgz#bc7b205a89d883452822cc75e138620c35e3291e"
- integrity sha512-jOin8xRZ/UytQeBpSXFqIzqU7Fi5TqgPNLlUsSB8kjJ76+FiGBfImF8KJu++c6J4jOldfJUtt0YmkRj2ZpSHTQ==
- dependencies:
- abort-controller "^3.0.0"
- extend "^3.0.2"
- https-proxy-agent "^5.0.0"
- is-stream "^2.0.0"
- node-fetch "^2.3.0"
-
-gcp-metadata@^4.2.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-4.2.0.tgz#3b424355ccdc240ee07c5791e2fd6a60a283d89a"
- integrity sha512-vQZD57cQkqIA6YPGXM/zc+PIZfNRFdukWGsGZ5+LcJzesi5xp6Gn7a02wRJi4eXPyArNMIYpPET4QMxGqtlk6Q==
- dependencies:
- gaxios "^3.0.0"
- json-bigint "^1.0.0"
-
-gcs-resumable-upload@^3.1.0:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/gcs-resumable-upload/-/gcs-resumable-upload-3.1.1.tgz#67c766a0555d6a352f9651b7603337207167d0de"
- integrity sha512-RS1osvAicj9+MjCc6jAcVL1Pt3tg7NK2C2gXM5nqD1Gs0klF2kj5nnAFSBy97JrtslMIQzpb7iSuxaG8rFWd2A==
- dependencies:
- abort-controller "^3.0.0"
- configstore "^5.0.0"
- extend "^3.0.2"
- gaxios "^3.0.0"
- google-auth-library "^6.0.0"
- pumpify "^2.0.0"
- stream-events "^1.0.4"
-
-get-stream@^5.1.0:
- version "5.2.0"
- 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"
-
-glob@^7.1.3:
- version "7.1.6"
- resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
- integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
- dependencies:
- fs.realpath "^1.0.0"
- inflight "^1.0.4"
- inherits "2"
- minimatch "^3.0.4"
- once "^1.3.0"
- path-is-absolute "^1.0.0"
-
-google-auth-library@^6.0.0, google-auth-library@^6.1.1:
- version "6.1.3"
- resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-6.1.3.tgz#39d868140b70d0c4b32c6f6d8f4ccc1400d84dca"
- integrity sha512-m9mwvY3GWbr7ZYEbl61isWmk+fvTmOt0YNUfPOUY2VH8K5pZlAIWJjxEi0PqR3OjMretyiQLI6GURMrPSwHQ2g==
- dependencies:
- arrify "^2.0.0"
- base64-js "^1.3.0"
- ecdsa-sig-formatter "^1.0.11"
- fast-text-encoding "^1.0.0"
- gaxios "^4.0.0"
- gcp-metadata "^4.2.0"
- gtoken "^5.0.4"
- jws "^4.0.0"
- lru-cache "^6.0.0"
-
-google-auth-library@^7.0.2:
- version "7.0.2"
- resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-7.0.2.tgz#cab6fc7f94ebecc97be6133d6519d9946ccf3e9d"
- integrity sha512-vjyNZR3pDLC0u7GHLfj+Hw9tGprrJwoMwkYGqURCXYITjCrP9HprOyxVV+KekdLgATtWGuDkQG2MTh0qpUPUgg==
- dependencies:
- arrify "^2.0.0"
- base64-js "^1.3.0"
- ecdsa-sig-formatter "^1.0.11"
- fast-text-encoding "^1.0.0"
- gaxios "^4.0.0"
- gcp-metadata "^4.2.0"
- gtoken "^5.0.4"
- jws "^4.0.0"
- lru-cache "^6.0.0"
-
-google-gax@^2.9.2:
- version "2.11.0"
- resolved "https://registry.yarnpkg.com/google-gax/-/google-gax-2.11.0.tgz#7219de6558747680489985de1bf769e46ec0771c"
- integrity sha512-aZMjCMw4wVssxplkO9Pq77zCHiYecvTYY51HeKOti0LLHaNrRo96F8h8NIA4hcWeh2u6COFX3YFmZyxrARXlGA==
- dependencies:
- "@grpc/grpc-js" "~1.2.0"
- "@grpc/proto-loader" "^0.5.1"
- "@types/long" "^4.0.0"
- abort-controller "^3.0.0"
- duplexify "^4.0.0"
- fast-text-encoding "^1.0.3"
- google-auth-library "^7.0.2"
- is-stream-ended "^0.1.4"
- node-fetch "^2.6.1"
- protobufjs "^6.10.2"
- retry-request "^4.0.0"
-
-google-p12-pem@^3.0.3:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/google-p12-pem/-/google-p12-pem-3.0.3.tgz#673ac3a75d3903a87f05878f3c75e06fc151669e"
- integrity sha512-wS0ek4ZtFx/ACKYF3JhyGe5kzH7pgiQ7J5otlumqR9psmWMYc+U9cErKlCYVYHoUaidXHdZ2xbo34kB+S+24hA==
- dependencies:
- node-forge "^0.10.0"
-
-graceful-fs@^4.1.11, graceful-fs@^4.1.2:
- version "4.2.4"
- resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
- integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==
-
-gtoken@^5.0.4:
- version "5.0.5"
- resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-5.0.5.tgz#e752d18538576777dfe237887e30fc0627870eae"
- integrity sha512-wvjkecutFh8kVfbcdBdUWqDRrXb+WrgD79DBDEYf1Om8S1FluhylhtFjrL7Tx69vNhh259qA3Q1P4sPtb+kUYw==
- dependencies:
- gaxios "^4.0.0"
- google-p12-pem "^3.0.3"
- jws "^4.0.0"
- mime "^2.2.0"
-
-hash-stream-validation@^0.2.2:
- version "0.2.4"
- resolved "https://registry.yarnpkg.com/hash-stream-validation/-/hash-stream-validation-0.2.4.tgz#ee68b41bf822f7f44db1142ec28ba9ee7ccb7512"
- integrity sha512-Gjzu0Xn7IagXVkSu9cSFuK1fqzwtLwFhNhVL8IFJijRNMgUttFbBSIAzKuSIrsFMO1+g1RlsoN49zPIbwPDMGQ==
-
-http-parser-js@>=0.5.1:
- version "0.5.2"
- resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.2.tgz#da2e31d237b393aae72ace43882dd7e270a8ff77"
- integrity sha512-opCO9ASqg5Wy2FNo7A0sxy71yGbbkJJXLdgMK04Tcypw9jr2MgWbyubb0+WdmDmGnFflO7fRbqbaihh/ENDlRQ==
-
-http-proxy-agent@^4.0.0:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a"
- integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==
- dependencies:
- "@tootallnate/once" "1"
- agent-base "6"
- debug "4"
-
-https-proxy-agent@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2"
- integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==
- dependencies:
- agent-base "6"
- debug "4"
-
-imurmurhash@^0.1.4:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
- integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
-
-inflight@^1.0.4:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
- integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
- dependencies:
- once "^1.3.0"
- wrappy "1"
-
-inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
- integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
-
-is-obj@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982"
- integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==
-
-is-stream-ended@^0.1.4:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/is-stream-ended/-/is-stream-ended-0.1.4.tgz#f50224e95e06bce0e356d440a4827cd35b267eda"
- integrity sha512-xj0XPvmr7bQFTvirqnFr50o0hQIh6ZItDqloxt5aJrR4NQsYeSsyFQERYGCAzfindAcnKjINnwEEgLx4IqVzQw==
-
-is-stream@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3"
- integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==
-
-is-typedarray@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
- integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
-
-isarray@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
- integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
-
-jpeg-js@^0.4.2:
- version "0.4.2"
- resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.4.2.tgz#8b345b1ae4abde64c2da2fe67ea216a114ac279d"
- integrity sha512-+az2gi/hvex7eLTMTlbRLOhH6P6WFdk2ITI8HJsaH2VqYO0I594zXSYEP+tf4FW+8Cy68ScDXoAsQdyQanv3sw==
-
-json-bigint@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/json-bigint/-/json-bigint-1.0.0.tgz#ae547823ac0cad8398667f8cd9ef4730f5b01ff1"
- integrity sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==
- dependencies:
- bignumber.js "^9.0.0"
-
-jsonwebtoken@^8.5.1:
- version "8.5.1"
- resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d"
- 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"
-
-jwa@^1.4.1:
- version "1.4.1"
- 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"
- ecdsa-sig-formatter "1.0.11"
- safe-buffer "^5.0.1"
-
-jwa@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/jwa/-/jwa-2.0.0.tgz#a7e9c3f29dae94027ebcaf49975c9345593410fc"
- integrity sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==
- dependencies:
- buffer-equal-constant-time "1.0.1"
- ecdsa-sig-formatter "1.0.11"
- safe-buffer "^5.0.1"
-
-jws@^3.2.2:
- version "3.2.2"
- resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304"
- integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==
- dependencies:
- jwa "^1.4.1"
- safe-buffer "^5.0.1"
-
-jws@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/jws/-/jws-4.0.0.tgz#2d4e8cf6a318ffaa12615e9dec7e86e6c97310f4"
- integrity sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==
- dependencies:
- jwa "^2.0.0"
- safe-buffer "^5.0.1"
-
-lodash.camelcase@^4.3.0:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
- integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY=
-
-lodash.includes@^4.3.0:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f"
- integrity sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=
-
-lodash.isboolean@^3.0.3:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6"
- integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=
-
-lodash.isinteger@^4.0.4:
- version "4.0.4"
- resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343"
- integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=
-
-lodash.isnumber@^3.0.3:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc"
- integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=
-
-lodash.isplainobject@^4.0.6:
- version "4.0.6"
- resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
- integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=
-
-lodash.isstring@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451"
- integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=
-
-lodash.once@^4.0.0:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
- integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=
-
-long@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28"
- integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==
-
-lru-cache@^6.0.0:
- version "6.0.0"
- resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
- integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
- dependencies:
- yallist "^4.0.0"
-
-make-dir@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f"
- integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==
- dependencies:
- semver "^6.0.0"
-
-mime-db@1.44.0:
- version "1.44.0"
- resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92"
- integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==
-
-"mime-db@>= 1.43.0 < 2":
- version "1.45.0"
- resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea"
- integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==
-
-mime-types@^2.0.8:
- version "2.1.27"
- resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f"
- integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==
- dependencies:
- mime-db "1.44.0"
-
-mime@^2.2.0, mime@^2.4.6:
- version "2.4.6"
- resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.6.tgz#e5b407c90db442f2beb5b162373d07b69affa4d1"
- integrity sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==
-
-mimic-fn@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
- integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
-
-minimatch@^3.0.4:
- version "3.0.4"
- resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
- integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
- dependencies:
- brace-expansion "^1.1.7"
-
-ms@2.1.2, ms@^2.1.1:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
- integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
-
-node-fetch@^2.3.0, node-fetch@^2.6.1:
- version "2.6.1"
- resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
- integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
-
-node-forge@^0.10.0:
- version "0.10.0"
- resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3"
- integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==
-
-once@^1.3.0, once@^1.3.1, once@^1.4.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
- integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
- dependencies:
- wrappy "1"
-
-onetime@^5.1.0:
- version "5.1.2"
- resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
- integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
- dependencies:
- mimic-fn "^2.1.0"
-
-p-limit@^3.0.1:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.0.2.tgz#1664e010af3cadc681baafd3e2a437be7b0fb5fe"
- integrity sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==
- dependencies:
- p-try "^2.0.0"
-
-p-try@^2.0.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
- integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
-
-path-is-absolute@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
- integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
-
-pend@~1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
- integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA=
-
-playwright-cli@^0.180.0:
- version "0.180.0"
- resolved "https://registry.yarnpkg.com/playwright-cli/-/playwright-cli-0.180.0.tgz#5e95a517732b12f0f70e88e4a60bfbd622149b2f"
- integrity sha512-T2mBkdIwSNz8K+wRYpZgPDWzS3pUjSomi+9W6ybg/FSTQvxceGg2n8upo4YGFkBrH4PyOcRTi+si+B7O6yRa+g==
-
-playwright@^1.9.2:
- version "1.9.2"
- resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.9.2.tgz#294910950b76ec4c3dfed6a1e9d28e9b8560b0f4"
- integrity sha512-Hsgfk3GZO+hgewRNW9xl9/tHjdZvVwxTseHagbiNpDf90PXICEh8UHXy/2eykeIXrZFMA6W6petEtRWNPi3gfQ==
- dependencies:
- commander "^6.1.0"
- debug "^4.1.1"
- extract-zip "^2.0.1"
- https-proxy-agent "^5.0.0"
- jpeg-js "^0.4.2"
- mime "^2.4.6"
- pngjs "^5.0.0"
- progress "^2.0.3"
- proper-lockfile "^4.1.1"
- proxy-from-env "^1.1.0"
- rimraf "^3.0.2"
- stack-utils "^2.0.3"
- ws "^7.3.1"
-
-pngjs@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-5.0.0.tgz#e79dd2b215767fd9c04561c01236df960bce7fbb"
- integrity sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==
-
-process-nextick-args@~2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
- integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
-
-progress@^2.0.3:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
- integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
-
-proper-lockfile@^4.1.1:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-4.1.1.tgz#284cf9db9e30a90e647afad69deb7cb06881262c"
- integrity sha512-1w6rxXodisVpn7QYvLk706mzprPTAPCYAqxMvctmPN3ekuRk/kuGkGc82pangZiAt4R3lwSuUzheTTn0/Yb7Zg==
- dependencies:
- graceful-fs "^4.1.11"
- retry "^0.12.0"
- signal-exit "^3.0.2"
-
-protobufjs@^6.10.2:
- version "6.10.2"
- resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.10.2.tgz#b9cb6bd8ec8f87514592ba3fdfd28e93f33a469b"
- integrity sha512-27yj+04uF6ya9l+qfpH187aqEzfCF4+Uit0I9ZBQVqK09hk/SQzKa2MUqUpXaVa7LOFRg1TSSr3lVxGOk6c0SQ==
- dependencies:
- "@protobufjs/aspromise" "^1.1.2"
- "@protobufjs/base64" "^1.1.2"
- "@protobufjs/codegen" "^2.0.4"
- "@protobufjs/eventemitter" "^1.1.0"
- "@protobufjs/fetch" "^1.1.0"
- "@protobufjs/float" "^1.0.2"
- "@protobufjs/inquire" "^1.1.0"
- "@protobufjs/path" "^1.1.2"
- "@protobufjs/pool" "^1.1.0"
- "@protobufjs/utf8" "^1.1.0"
- "@types/long" "^4.0.1"
- "@types/node" "^13.7.0"
- long "^4.0.0"
-
-protobufjs@^6.8.6:
- version "6.10.1"
- resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.10.1.tgz#e6a484dd8f04b29629e9053344e3970cccf13cd2"
- integrity sha512-pb8kTchL+1Ceg4lFd5XUpK8PdWacbvV5SK2ULH2ebrYtl4GjJmS24m6CKME67jzV53tbJxHlnNOSqQHbTsR9JQ==
- dependencies:
- "@protobufjs/aspromise" "^1.1.2"
- "@protobufjs/base64" "^1.1.2"
- "@protobufjs/codegen" "^2.0.4"
- "@protobufjs/eventemitter" "^1.1.0"
- "@protobufjs/fetch" "^1.1.0"
- "@protobufjs/float" "^1.0.2"
- "@protobufjs/inquire" "^1.1.0"
- "@protobufjs/path" "^1.1.2"
- "@protobufjs/pool" "^1.1.0"
- "@protobufjs/utf8" "^1.1.0"
- "@types/long" "^4.0.1"
- "@types/node" "^13.7.0"
- long "^4.0.0"
-
-proxy-from-env@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
- integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
-
-pump@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
- integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==
- dependencies:
- end-of-stream "^1.1.0"
- once "^1.3.1"
-
-pumpify@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-2.0.1.tgz#abfc7b5a621307c728b551decbbefb51f0e4aa1e"
- integrity sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw==
- dependencies:
- duplexify "^4.1.1"
- inherits "^2.0.3"
- pump "^3.0.0"
-
-readable-stream@^2.0.0:
- version "2.3.7"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
- integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
- dependencies:
- core-util-is "~1.0.0"
- inherits "~2.0.3"
- isarray "~1.0.0"
- process-nextick-args "~2.0.0"
- safe-buffer "~5.1.1"
- string_decoder "~1.1.1"
- util-deprecate "~1.0.1"
-
-readable-stream@^3.0.2, readable-stream@^3.1.1:
- version "3.6.0"
- 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"
-
-retry-request@^4.0.0, retry-request@^4.1.1:
- version "4.1.3"
- resolved "https://registry.yarnpkg.com/retry-request/-/retry-request-4.1.3.tgz#d5f74daf261372cff58d08b0a1979b4d7cab0fde"
- integrity sha512-QnRZUpuPNgX0+D1xVxul6DbJ9slvo4Rm6iV/dn63e048MvGbUZiKySVt6Tenp04JqmchxjiLltGerOJys7kJYQ==
- dependencies:
- debug "^4.1.1"
-
-retry@^0.12.0:
- version "0.12.0"
- resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b"
- integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=
-
-rimraf@^3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
- integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
- dependencies:
- glob "^7.1.3"
-
-safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@~5.2.0:
- 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:
- version "5.1.2"
- resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
- integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
-
-semver@^5.6.0:
- version "5.7.1"
- resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
- integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
-
-semver@^6.0.0, semver@^6.2.0:
- version "6.3.0"
- resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
- integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
-
-signal-exit@^3.0.2:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
- integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
-
-snakeize@^0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/snakeize/-/snakeize-0.1.0.tgz#10c088d8b58eb076b3229bb5a04e232ce126422d"
- integrity sha1-EMCI2LWOsHazIpu1oE4jLOEmQi0=
-
-stack-utils@^2.0.3:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.3.tgz#cd5f030126ff116b78ccb3c027fe302713b61277"
- integrity sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw==
- dependencies:
- escape-string-regexp "^2.0.0"
-
-stream-events@^1.0.1, stream-events@^1.0.4, stream-events@^1.0.5:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/stream-events/-/stream-events-1.0.5.tgz#bbc898ec4df33a4902d892333d47da9bf1c406d5"
- integrity sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==
- dependencies:
- stubs "^3.0.0"
-
-stream-shift@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d"
- integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==
-
-streamsearch@0.1.2:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a"
- integrity sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=
-
-string_decoder@^1.1.1:
- version "1.3.0"
- 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"
-
-string_decoder@~1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
- integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
- dependencies:
- safe-buffer "~5.1.0"
-
-stubs@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/stubs/-/stubs-3.0.0.tgz#e8d2ba1fa9c90570303c030b6900f7d5f89abe5b"
- integrity sha1-6NK6H6nJBXAwPAMLaQD31fiavls=
-
-teeny-request@^7.0.0:
- version "7.0.1"
- resolved "https://registry.yarnpkg.com/teeny-request/-/teeny-request-7.0.1.tgz#bdd41fdffea5f8fbc0d29392cb47bec4f66b2b4c"
- integrity sha512-sasJmQ37klOlplL4Ia/786M5YlOcoLGQyq2TE4WHSRupbAuDaQW0PfVxV4MtdBtRJ4ngzS+1qim8zP6Zp35qCw==
- dependencies:
- http-proxy-agent "^4.0.0"
- https-proxy-agent "^5.0.0"
- node-fetch "^2.6.1"
- stream-events "^1.0.5"
- uuid "^8.0.0"
-
-tslib@^1.11.1:
- version "1.14.1"
- resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
- integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
-
-typedarray-to-buffer@^3.1.5:
- version "3.1.5"
- resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080"
- integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==
- dependencies:
- is-typedarray "^1.0.0"
-
-typedarray@^0.0.6:
- version "0.0.6"
- resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
- integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
-
-unique-string@^2.0.0:
- version "2.0.0"
- 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"
-
-util-deprecate@^1.0.1, util-deprecate@~1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
- integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
-
-uuid@^8.0.0:
- version "8.3.1"
- resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.1.tgz#2ba2e6ca000da60fce5a196954ab241131e05a31"
- integrity sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==
-
-websocket-driver@>=0.5.1:
- version "0.7.4"
- resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760"
- integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==
- dependencies:
- http-parser-js ">=0.5.1"
- safe-buffer ">=5.1.0"
- websocket-extensions ">=0.1.1"
-
-websocket-extensions@>=0.1.1:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42"
- integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==
-
-wrappy@1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
- integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
-
-write-file-atomic@^3.0.0:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8"
- integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==
- dependencies:
- imurmurhash "^0.1.4"
- is-typedarray "^1.0.0"
- signal-exit "^3.0.2"
- typedarray-to-buffer "^3.1.5"
-
-ws@^7.3.1:
- version "7.4.6"
- resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c"
- integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==
-
-xdg-basedir@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13"
- integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==
-
-yallist@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
- integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
-
-yauzl@^2.10.0:
- version "2.10.0"
- resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"
- integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=
- dependencies:
- buffer-crc32 "~0.2.3"
- fd-slicer "~1.1.0"
diff --git a/firebase.json b/firebase.json
new file mode 100644
index 000000000..dd8815ef3
--- /dev/null
+++ b/firebase.json
@@ -0,0 +1,13 @@
+{
+ "hosting": {
+ "target": "rowy",
+ "public": "build",
+ "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
+ "rewrites": [
+ {
+ "source": "**",
+ "destination": "/index.html"
+ }
+ ]
+ }
+}
diff --git a/ft_actions/firebase.json b/ft_actions/firebase.json
deleted file mode 100644
index 67a150108..000000000
--- a/ft_actions/firebase.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "functions": {
- "predeploy": [
- "npm --prefix \"$RESOURCE_DIR\" run lint",
- "npm --prefix \"$RESOURCE_DIR\" run build"
- ]
- }
-}
diff --git a/ft_actions/functions/.eslintrc.js b/ft_actions/functions/.eslintrc.js
deleted file mode 100644
index 0c0d94621..000000000
--- a/ft_actions/functions/.eslintrc.js
+++ /dev/null
@@ -1,64 +0,0 @@
-module.exports = {
- env: {
- browser: true,
- es6: true,
- node: true,
- },
- extends: ["plugin:import/errors", "plugin:import/warnings"],
- parser: "@typescript-eslint/parser",
- parserOptions: {
- project: "tsconfig.json",
- sourceType: "module",
- },
- plugins: ["@typescript-eslint", "import"],
- rules: {
- "@typescript-eslint/adjacent-overload-signatures": "error",
- "@typescript-eslint/no-empty-function": "error",
- "@typescript-eslint/no-empty-interface": "warn",
- "@typescript-eslint/no-floating-promises": "error",
- "@typescript-eslint/no-namespace": "error",
- "@typescript-eslint/no-unnecessary-type-assertion": "error",
- "@typescript-eslint/prefer-for-of": "warn",
- "@typescript-eslint/triple-slash-reference": "error",
- "@typescript-eslint/unified-signatures": "warn",
- "comma-dangle": "warn",
- "constructor-super": "error",
- eqeqeq: ["warn", "always"],
- "import/no-deprecated": "warn",
- "import/no-extraneous-dependencies": "error",
- "import/no-unassigned-import": "warn",
- "no-cond-assign": "error",
- "no-duplicate-case": "error",
- "no-duplicate-imports": "error",
- "no-empty": [
- "error",
- {
- allowEmptyCatch: true,
- },
- ],
- "no-invalid-this": "error",
- "no-new-wrappers": "error",
- "no-param-reassign": "error",
- "no-redeclare": "error",
- "no-sequences": "error",
- "no-shadow": [
- "error",
- {
- hoist: "all",
- },
- ],
- "no-throw-literal": "error",
- "no-unsafe-finally": "error",
- "no-unused-labels": "error",
- "no-var": "warn",
- "no-void": "error",
- "prefer-const": "warn",
- },
- settings: {
- jsdoc: {
- tagNamePreference: {
- returns: "return",
- },
- },
- },
-};
diff --git a/ft_actions/functions/.gitignore b/ft_actions/functions/.gitignore
deleted file mode 100644
index cef9251f0..000000000
--- a/ft_actions/functions/.gitignore
+++ /dev/null
@@ -1,12 +0,0 @@
-# Compiled JavaScript files
-**/*.js
-**/*.js.map
-
-# Except the ESLint config file
-!.eslintrc.js
-
-# TypeScript v1 declaration files
-typings/
-
-# Node.js dependency directory
-node_modules/
diff --git a/ft_actions/functions/package.json b/ft_actions/functions/package.json
deleted file mode 100644
index 2757c6894..000000000
--- a/ft_actions/functions/package.json
+++ /dev/null
@@ -1,36 +0,0 @@
-{
- "name": "functions",
- "scripts": {
- "lint": "tslint --project tsconfig.json",
- "build": "tsc",
- "serve": "npm run build && firebase serve --only functions",
- "shell": "npm run build && firebase functions:shell",
- "start": "npm run shell",
- "deployFT": "echo 'n\n' | firebase deploy --interactive",
- "logs": "firebase functions:log"
- },
- "engines": {
- "node": "14"
- },
- "main": "lib/index.js",
- "dependencies": {
- "firebase-admin": "^9.11.0",
- "firebase-functions": "^3.14.1",
- "lodash": "^4.17.21"
- },
- "devDependencies": {
- "firebase-tools": "^8.7.0",
- "husky": "^4.2.5",
- "prettier": "^2.1.1",
- "pretty-quick": "^3.0.0",
- "ts-node": "^8.6.2",
- "tslint": "^6.1.0",
- "typescript": "^3.2.2"
- },
- "husky": {
- "hooks": {
- "pre-commit": "pretty-quick --staged"
- }
- },
- "private": true
-}
diff --git a/ft_actions/functions/src/firebaseConfig.ts b/ft_actions/functions/src/firebaseConfig.ts
deleted file mode 100644
index db32295dc..000000000
--- a/ft_actions/functions/src/firebaseConfig.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-// Initialize Firebase Admin
-import * as functions from "firebase-functions";
-import * as admin from "firebase-admin";
-admin.initializeApp();
-
-// Initialize Cloud Firestore Database
-export const db = admin.firestore();
-// Initialize Auth
-export const auth = admin.auth();
-
-const settings = { timestampsInSnapshots: true, ignoreUndefinedProperties: true};
-db.settings(settings);
-export const env = functions.config();
diff --git a/ft_actions/functions/src/index.ts b/ft_actions/functions/src/index.ts
deleted file mode 100644
index eeda2f9e7..000000000
--- a/ft_actions/functions/src/index.ts
+++ /dev/null
@@ -1,126 +0,0 @@
-import * as functions from "firebase-functions";
-import * as _ from "lodash";
-import { db, auth } from "./firebaseConfig";
-import * as admin from "firebase-admin";
-import utilFns from "./utils";
-type ActionData = {
- ref: {
- id: string;
- path: string;
- parentId: string;
- tablePath: string;
- };
- schemaDocPath?: string;
- column: any;
- action: "run" | "redo" | "undo";
- actionParams: any;
-};
-
-const missingFieldsReducer = (data: any) => (acc: string[], curr: string) => {
- if (data[curr] === undefined) {
- return [...acc, curr];
- } else return acc;
-};
-
-const generateSchemaDocPath = (tablePath) => {
- const pathComponents = tablePath.split("/");
- return `_FIRETABLE_/settings/${
- pathComponents[1] === "table" ? "schema" : "groupSchema"
- }/${pathComponents[2]}`;
-};
-const serverTimestamp = admin.firestore.FieldValue.serverTimestamp;
-
-export const actionScript = functions.https.onCall(
- async (data: ActionData, context: functions.https.CallableContext) => {
- try {
- if (!context) {
- throw Error(`You are unauthenticated`);
- }
-
- const { ref, actionParams, column, action, schemaDocPath } = data;
- const _schemaDocPath =
- schemaDocPath ?? generateSchemaDocPath(ref.tablePath);
- const [schemaDoc, rowQuery] = await Promise.all([
- db.doc(_schemaDocPath).get(),
- db.doc(ref.path).get(),
- ]);
- const row = rowQuery.data();
- const schemaDocData = schemaDoc.data();
- if (!schemaDocData) {
- return {
- success: false,
- message: "no schema found",
- };
- }
- const config = schemaDocData.columns[column.key].config;
- const { script, requiredRoles, requiredFields } = config;
- if (!requiredRoles || requiredRoles.length === 0) {
- throw Error(`You need to specify at least one role to run this script`);
- }
- if (!utilFns.hasAnyRole(requiredRoles, context)) {
- throw Error(`You don't have the required roles permissions`);
- }
-
- const missingRequiredFields = requiredFields
- ? requiredFields.reduce(missingFieldsReducer(row), [])
- : [];
- if (missingRequiredFields.length > 0) {
- throw new Error(
- `Missing required fields:${missingRequiredFields.join(", ")}`
- );
- }
- const result: {
- message: string;
- status: string;
- success: boolean;
- } = await eval(
- `async({row,db, ref,auth,utilFns,actionParams,context})=>{${
- action === "undo" ? config["undo.script"] : script
- }}`
- )({ row, db, auth, utilFns, ref, actionParams, context });
- if (result.success) {
- const cellValue = {
- redo: config["redo.enabled"],
- status: result.status,
- completedAt: serverTimestamp(),
- ranBy: context.auth!.token.email,
- undo: config["undo.enabled"],
- };
- try {
- const userDoc = await db
- .collection("_FT_USERS")
- .doc(context.auth!.uid)
- .get();
- const user = userDoc?.get("user");
- await db.doc(ref.path).update({
- [column.key]: cellValue,
- _ft_updatedBy: user
- ? {
- ...user,
- ...context.auth!,
- timestamp: new Date(),
- }
- : null,
- });
- } catch (error) {
- // handle failed edit log update
- }
-
- return {
- ...result,
- cellValue,
- };
- } else
- return {
- success: false,
- message: result.message,
- };
- } catch (error) {
- return {
- success: false,
- error,
- message: error.message,
- };
- }
- }
-);
diff --git a/ft_actions/functions/src/utils/auth.ts b/ft_actions/functions/src/utils/auth.ts
deleted file mode 100644
index 67857e2ae..000000000
--- a/ft_actions/functions/src/utils/auth.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import * as functions from "firebase-functions";
-
-export const hasAnyRole = (
- authorizedRoles: string[],
- context: functions.https.CallableContext
-) => {
- if (!context.auth || !context.auth.token.roles) return false;
- const userRoles = context.auth.token.roles as string[];
- const authorization = authorizedRoles.reduce(
- (authorized: boolean, role: string) => {
- if (userRoles.includes(role)) return true;
- else return authorized;
- },
- false
- );
- return authorization;
-};
diff --git a/ft_actions/functions/src/utils/index.ts b/ft_actions/functions/src/utils/index.ts
deleted file mode 100644
index 81dba8653..000000000
--- a/ft_actions/functions/src/utils/index.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import * as admin from "firebase-admin";
-export const serverTimestamp = admin.firestore.FieldValue.serverTimestamp;
-import { hasAnyRole } from "./auth";
-
-const characters =
- "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
-export function generateId(length: number): string {
- let result = "";
- const charactersLength = characters.length;
- for (let i = 0; i < length; i++) {
- result += characters.charAt(Math.floor(Math.random() * charactersLength));
- }
- return result;
-}
-
-const hasRequiredFields = (requiredFields: string[], data: any) =>
- requiredFields.reduce((acc: boolean, currField: string) => {
- if (data[currField] === undefined || data[currField] === null) return false;
- else return acc;
- }, true);
-async function asyncForEach(array: any[], callback: Function) {
- for (let index = 0; index < array.length; index++) {
- await callback(array[index], index, array);
- }
-}
-const identifyTriggerType = (beforeData: any, afterData: any) =>
- Boolean(beforeData) && Boolean(afterData)
- ? "update"
- : Boolean(afterData)
- ? "create"
- : "delete";
-
-export default {
- hasRequiredFields,
- generateId,
- serverTimestamp,
- hasAnyRole,
- asyncForEach,
- identifyTriggerType,
-};
diff --git a/ft_actions/functions/tsconfig.json b/ft_actions/functions/tsconfig.json
deleted file mode 100644
index 56ffd02b4..000000000
--- a/ft_actions/functions/tsconfig.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "compilerOptions": {
- "module": "CommonJS",
- "noImplicitReturns": true,
- "noUnusedLocals": true,
- "outDir": "lib",
- "sourceMap": true,
- "strict": true,
- "noImplicitAny": false,
- "target": "ESNext"
- },
- "compileOnSave": true,
- "include": ["src"]
-}
diff --git a/ft_actions/functions/tslint.json b/ft_actions/functions/tslint.json
deleted file mode 100644
index e28661855..000000000
--- a/ft_actions/functions/tslint.json
+++ /dev/null
@@ -1,119 +0,0 @@
-{
- "rules": {
- // -- Strict errors --
- // These lint rules are likely always a good idea.
-
- // Force function overloads to be declared together. This ensures readers understand APIs.
- "adjacent-overload-signatures": true,
-
- // Do not allow the subtle/obscure comma operator.
- "ban-comma-operator": true,
-
- // Do not allow internal modules or namespaces . These are deprecated in favor of ES6 modules.
- "no-namespace": true,
-
- // Do not allow parameters to be reassigned. To avoid bugs, developers should instead assign new values to new vars.
- "no-parameter-reassignment": true,
-
- // Force the use of ES6-style imports instead of /// imports.
- "no-reference": true,
-
- // Do not allow type assertions that do nothing. This is a big warning that the developer may not understand the
- // code currently being edited (they may be incorrectly handling a different type case that does not exist).
- "no-unnecessary-type-assertion": true,
-
- // Disallow nonsensical label usage.
- "label-position": true,
-
- // Disallows the (often typo) syntax if (var1 = var2). Replace with if (var2) { var1 = var2 }.
- "no-conditional-assignment": true,
-
- // Disallows constructors for primitive types (e.g. new Number('123'), though Number('123') is still allowed).
- "no-construct": true,
-
- // Do not allow super() to be called twice in a constructor.
- "no-duplicate-super": true,
-
- // Do not allow the same case to appear more than once in a switch block.
- "no-duplicate-switch-case": true,
-
- // Do not allow a variable to be declared more than once in the same block. Consider function parameters in this
- // rule.
- "no-duplicate-variable": [true, "check-parameters"],
-
- // Disallows a variable definition in an inner scope from shadowing a variable in an outer scope. Developers should
- // instead use a separate variable name.
- "no-shadowed-variable": true,
-
- // Empty blocks are almost never needed. Allow the one general exception: empty catch blocks.
- "no-empty": [true, "allow-empty-catch"],
-
- // Functions must either be handled directly (e.g. with a catch() handler) or returned to another function.
- // This is a major source of errors in Cloud Functions and the team strongly recommends leaving this rule on.
- "no-floating-promises": true,
-
- // Do not allow any imports for modules that are not in package.json. These will almost certainly fail when
- // deployed.
- "no-implicit-dependencies": true,
-
- // The 'this' keyword can only be used inside of classes.
- "no-invalid-this": true,
-
- // Do not allow strings to be thrown because they will not include stack traces. Throw Errors instead.
- "no-string-throw": true,
-
- // Disallow control flow statements, such as return, continue, break, and throw in finally blocks.
- "no-unsafe-finally": true,
-
- // Do not allow variables to be used before they are declared.
- "no-use-before-declare": true,
-
- // Expressions must always return a value. Avoids common errors like const myValue = functionReturningVoid();
- "no-void-expression": [true, "ignore-arrow-function-shorthand"],
-
- // Disallow duplicate imports in the same file.
- "no-duplicate-imports": true,
-
- // -- Strong Warnings --
- // These rules should almost never be needed, but may be included due to legacy code.
- // They are left as a warning to avoid frustration with blocked deploys when the developer
- // understand the warning and wants to deploy anyway.
-
- // Warn when an empty interface is defined. These are generally not useful.
- "no-empty-interface": { "severity": "warning" },
-
- // Warn when an import will have side effects.
- "no-import-side-effect": { "severity": "warning" },
-
- // Warn when variables are defined with var. Var has subtle meaning that can lead to bugs. Strongly prefer const for
- // most values and let for values that will change.
- "no-var-keyword": { "severity": "warning" },
-
- // Prefer === and !== over == and !=. The latter operators support overloads that are often accidental.
- "triple-equals": { "severity": "warning" },
-
- // Warn when using deprecated APIs.
- "deprecation": { "severity": "warning" },
-
- // -- Light Warnings --
- // These rules are intended to help developers use better style. Simpler code has fewer bugs. These would be "info"
- // if TSLint supported such a level.
-
- // prefer for( ... of ... ) to an index loop when the index is only used to fetch an object from an array.
- // (Even better: check out utils like .map if transforming an array!)
- "prefer-for-of": { "severity": "warning" },
-
- // Warns if function overloads could be unified into a single function with optional or rest parameters.
- "unified-signatures": { "severity": "warning" },
-
- // Prefer const for values that will not change. This better documents code.
- "prefer-const": { "severity": "warning" },
-
- // Multi-line object literals and function calls should have a trailing comma. This helps avoid merge conflicts.
- "trailing-comma": { "severity": "warning" }
- },
- "linterOptions": {
- "exclude": ["./generator/templates/**"]
- },
- "defaultSeverity": "error"
-}
diff --git a/ft_actions/functions/yarn.lock b/ft_actions/functions/yarn.lock
deleted file mode 100644
index 3a6fdd6c8..000000000
--- a/ft_actions/functions/yarn.lock
+++ /dev/null
@@ -1,5265 +0,0 @@
-# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
-# yarn lockfile v1
-
-
-"@apidevtools/json-schema-ref-parser@^9.0.3":
- version "9.0.9"
- resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz#d720f9256e3609621280584f2b47ae165359268b"
- integrity sha512-GBD2Le9w2+lVFoc4vswGI/TjkNIZSVp7+9xPf+X3uidBfWnAeUWmquteSyt0+VCrhNMWj/FTABISQrD3Z/YA+w==
- dependencies:
- "@jsdevtools/ono" "^7.1.3"
- "@types/json-schema" "^7.0.6"
- call-me-maybe "^1.0.1"
- js-yaml "^4.1.0"
-
-"@babel/code-frame@^7.0.0":
- version "7.14.5"
- resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb"
- integrity sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==
- dependencies:
- "@babel/highlight" "^7.14.5"
-
-"@babel/helper-validator-identifier@^7.14.5":
- version "7.14.8"
- resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.8.tgz#32be33a756f29e278a0d644fa08a2c9e0f88a34c"
- integrity sha512-ZGy6/XQjllhYQrNw/3zfWRwZCTVSiBLZ9DHVZxn9n2gip/7ab8mv2TWlKPIBk26RwedCBoWdjLmn+t9na2Gcow==
-
-"@babel/highlight@^7.14.5":
- version "7.14.5"
- resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9"
- integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==
- dependencies:
- "@babel/helper-validator-identifier" "^7.14.5"
- chalk "^2.0.0"
- js-tokens "^4.0.0"
-
-"@dabh/diagnostics@^2.0.2":
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.2.tgz#290d08f7b381b8f94607dc8f471a12c675f9db31"
- integrity sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==
- dependencies:
- colorspace "1.1.x"
- enabled "2.0.x"
- kuler "^2.0.0"
-
-"@firebase/app-types@0.6.2":
- version "0.6.2"
- resolved "https://registry.yarnpkg.com/@firebase/app-types/-/app-types-0.6.2.tgz#8578cb1061a83ced4570188be9e225d54e0f27fb"
- integrity sha512-2VXvq/K+n8XMdM4L2xy5bYp2ZXMawJXluUIDzUBvMthVR+lhxK4pfFiqr1mmDbv9ydXvEAuFsD+6DpcZuJcSSw==
-
-"@firebase/auth-interop-types@0.1.6":
- version "0.1.6"
- resolved "https://registry.yarnpkg.com/@firebase/auth-interop-types/-/auth-interop-types-0.1.6.tgz#5ce13fc1c527ad36f1bb1322c4492680a6cf4964"
- integrity sha512-etIi92fW3CctsmR9e3sYM3Uqnoq861M0Id9mdOPF6PWIg38BXL5k4upCNBggGUpLIS0H1grMOvy/wn1xymwe2g==
-
-"@firebase/component@0.5.4":
- version "0.5.4"
- resolved "https://registry.yarnpkg.com/@firebase/component/-/component-0.5.4.tgz#546c3e9c98c9990fb6af7ea9f0b4997312aacc19"
- integrity sha512-KoLDPTsvxWr6FT9kn/snffJItaWXZLHLJlZVKiiw+flKE6MVA8Eec+ctvM2zcsMZzC2Z47gFnVqywfBlOevmpQ==
- dependencies:
- "@firebase/util" "1.1.0"
- tslib "^2.1.0"
-
-"@firebase/database-types@0.7.2", "@firebase/database-types@^0.7.2":
- version "0.7.2"
- resolved "https://registry.yarnpkg.com/@firebase/database-types/-/database-types-0.7.2.tgz#449c4b36ec59a1ad9089797b540e2ba1c0d4fcbf"
- integrity sha512-cdAd/dgwvC0r3oLEDUR+ULs1vBsEvy0b27nlzKhU6LQgm9fCDzgaH9nFGv8x+S9dly4B0egAXkONkVoWcOAisg==
- dependencies:
- "@firebase/app-types" "0.6.2"
-
-"@firebase/database@^0.10.0":
- version "0.10.8"
- resolved "https://registry.yarnpkg.com/@firebase/database/-/database-0.10.8.tgz#819713c87aab5834dbd8856f0ad19741f7abfdb6"
- integrity sha512-LCjQ6ELOm9TrENV0FuH3grkLTT0gPjBQC7K4dK2ggw39hSzmw09/WKVCmz0mCZtDDfxCiv+5Q6Md/w3zz6awEw==
- dependencies:
- "@firebase/auth-interop-types" "0.1.6"
- "@firebase/component" "0.5.4"
- "@firebase/database-types" "0.7.2"
- "@firebase/logger" "0.2.6"
- "@firebase/util" "1.1.0"
- faye-websocket "0.11.3"
- tslib "^2.1.0"
-
-"@firebase/logger@0.2.6":
- version "0.2.6"
- resolved "https://registry.yarnpkg.com/@firebase/logger/-/logger-0.2.6.tgz#3aa2ca4fe10327cabf7808bd3994e88db26d7989"
- integrity sha512-KIxcUvW/cRGWlzK9Vd2KB864HlUnCfdTH0taHE0sXW5Xl7+W68suaeau1oKNEqmc3l45azkd4NzXTCWZRZdXrw==
-
-"@firebase/util@1.1.0":
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/@firebase/util/-/util-1.1.0.tgz#add2d57d0b2307a932520abdee303b66be0ac8b0"
- integrity sha512-lfuSASuPKNdfebuFR8rjFamMQUPH9iiZHcKS755Rkm/5gRT0qC7BMhCh3ZkHf7NVbplzIc/GhmX2jM+igDRCag==
- dependencies:
- tslib "^2.1.0"
-
-"@google-cloud/common@^3.7.0":
- version "3.7.0"
- resolved "https://registry.yarnpkg.com/@google-cloud/common/-/common-3.7.0.tgz#ee3fba75aeaa614978aebf8740380670026592aa"
- integrity sha512-oFgpKLjH9JTOAyQd3kB36iSuH8wNSpDKb1TywlB6zcsG0xmJFxLutmfPhz03KUxRMNQOZ1K1Gc9BYvJifVnGVA==
- dependencies:
- "@google-cloud/projectify" "^2.0.0"
- "@google-cloud/promisify" "^2.0.0"
- arrify "^2.0.1"
- duplexify "^4.1.1"
- ent "^2.2.0"
- extend "^3.0.2"
- google-auth-library "^7.0.2"
- retry-request "^4.2.2"
- teeny-request "^7.0.0"
-
-"@google-cloud/firestore@^4.5.0":
- version "4.13.2"
- resolved "https://registry.yarnpkg.com/@google-cloud/firestore/-/firestore-4.13.2.tgz#579301cbb956fb355bd1844743029cfcd83e9a39"
- integrity sha512-zHxfZAeMtPBJYK1sLRPY/BBmML9ic4HreJiEaRZxBsDynFM9nljuP10gIrVca8/Bcl8Kv8vUz9Aa11Gfdl34iA==
- dependencies:
- fast-deep-equal "^3.1.1"
- functional-red-black-tree "^1.0.1"
- google-gax "^2.17.1"
- protobufjs "^6.8.6"
-
-"@google-cloud/paginator@^2.0.0":
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/@google-cloud/paginator/-/paginator-2.0.3.tgz#c7987ad05d1c3ebcef554381be80e9e8da4e4882"
- integrity sha512-kp/pkb2p/p0d8/SKUu4mOq8+HGwF8NPzHWkj+VKrIPQPyMRw8deZtrO/OcSiy9C/7bpfU5Txah5ltUNfPkgEXg==
- dependencies:
- arrify "^2.0.0"
- extend "^3.0.2"
-
-"@google-cloud/paginator@^3.0.0":
- version "3.0.5"
- resolved "https://registry.yarnpkg.com/@google-cloud/paginator/-/paginator-3.0.5.tgz#9d6b96c421a89bd560c1bc2c197c7611ef21db6c"
- integrity sha512-N4Uk4BT1YuskfRhKXBs0n9Lg2YTROZc6IMpkO/8DIHODtm5s3xY8K5vVBo23v/2XulY3azwITQlYWgT4GdLsUw==
- dependencies:
- arrify "^2.0.0"
- extend "^3.0.2"
-
-"@google-cloud/precise-date@^1.0.0":
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/@google-cloud/precise-date/-/precise-date-1.0.3.tgz#39c600ed52213f4158692a72c90d13b2162a93d2"
- integrity sha512-wWnDGh9y3cJHLuVEY8t6un78vizzMWsS7oIWKeFtPj+Ndy+dXvHW0HTx29ZUhen+tswSlQYlwFubvuRP5kKdzQ==
-
-"@google-cloud/projectify@^1.0.0":
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/@google-cloud/projectify/-/projectify-1.0.4.tgz#28daabebba6579ed998edcadf1a8f3be17f3b5f0"
- integrity sha512-ZdzQUN02eRsmTKfBj9FDL0KNDIFNjBn/d6tHQmA/+FImH5DO6ZV8E7FzxMgAUiVAUq41RFAkb25p1oHOZ8psfg==
-
-"@google-cloud/projectify@^2.0.0":
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/@google-cloud/projectify/-/projectify-2.1.0.tgz#3df145c932e244cdeb87a30d93adce615bc69e6d"
- integrity sha512-qbpidP/fOvQNz3nyabaVnZqcED1NNzf7qfeOlgtAZd9knTwY+KtsGRkYpiQzcATABy4gnGP2lousM3S0nuWVzA==
-
-"@google-cloud/promisify@^1.0.0":
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/@google-cloud/promisify/-/promisify-1.0.4.tgz#ce86ffa94f9cfafa2e68f7b3e4a7fad194189723"
- integrity sha512-VccZDcOql77obTnFh0TbNED/6ZbbmHDf8UMNnzO1d5g9V0Htfm4k5cllY8P1tJsRKC3zWYGRLaViiupcgVjBoQ==
-
-"@google-cloud/promisify@^2.0.0":
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/@google-cloud/promisify/-/promisify-2.0.3.tgz#f934b5cdc939e3c7039ff62b9caaf59a9d89e3a8"
- integrity sha512-d4VSA86eL/AFTe5xtyZX+ePUjE8dIFu2T8zmdeNBSa5/kNgXPCx/o/wbFNHAGLJdGnk1vddRuMESD9HbOC8irw==
-
-"@google-cloud/pubsub@^1.7.0":
- version "1.7.3"
- resolved "https://registry.yarnpkg.com/@google-cloud/pubsub/-/pubsub-1.7.3.tgz#0fa51d67eb4db979a66b05738d81c3cef992b5bf"
- integrity sha512-v+KdeaOS17WtHnsDf2bPGxKDT9HIRPYo3n+WsAEmvAzDHnh8q65mFcuYoQxuy2iRhmN/1ql2a0UU2tAAL7XZ8Q==
- dependencies:
- "@google-cloud/paginator" "^2.0.0"
- "@google-cloud/precise-date" "^1.0.0"
- "@google-cloud/projectify" "^1.0.0"
- "@google-cloud/promisify" "^1.0.0"
- "@types/duplexify" "^3.6.0"
- "@types/long" "^4.0.0"
- arrify "^2.0.0"
- async-each "^1.0.1"
- extend "^3.0.2"
- google-auth-library "^5.5.0"
- google-gax "^1.14.2"
- is-stream-ended "^0.1.4"
- lodash.snakecase "^4.1.1"
- p-defer "^3.0.0"
- protobufjs "^6.8.1"
-
-"@google-cloud/storage@^5.3.0":
- version "5.11.0"
- resolved "https://registry.yarnpkg.com/@google-cloud/storage/-/storage-5.11.0.tgz#f2414358f093034410bb03410176a5dcabc7bdf8"
- integrity sha512-UgdAwBelXpQhubYOHw0U/hDxCXIXFT2TqDc0JWUxtg+BeePZC0ohoFM/b/tJffE28AZW0urTQax5xbRNoDA1Sw==
- dependencies:
- "@google-cloud/common" "^3.7.0"
- "@google-cloud/paginator" "^3.0.0"
- "@google-cloud/promisify" "^2.0.0"
- arrify "^2.0.0"
- async-retry "^1.3.1"
- compressible "^2.0.12"
- date-and-time "^1.0.0"
- duplexify "^4.0.0"
- extend "^3.0.2"
- gcs-resumable-upload "^3.3.0"
- get-stream "^6.0.0"
- hash-stream-validation "^0.2.2"
- mime "^2.2.0"
- mime-types "^2.0.8"
- onetime "^5.1.0"
- p-limit "^3.0.1"
- pumpify "^2.0.0"
- snakeize "^0.1.0"
- stream-events "^1.0.1"
- xdg-basedir "^4.0.0"
-
-"@grpc/grpc-js@^0.6.12":
- version "0.6.18"
- resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-0.6.18.tgz#ba3b3dfef869533161d192a385412a4abd0db127"
- integrity sha512-uAzv/tM8qpbf1vpx1xPMfcUMzbfdqJtdCYAqY/LsLeQQlnTb4vApylojr+wlCyr7bZeg3AFfHvtihnNOQQt/nA==
- dependencies:
- semver "^6.2.0"
-
-"@grpc/grpc-js@~1.3.0", "@grpc/grpc-js@~1.3.6":
- version "1.3.6"
- resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.3.6.tgz#6e2d17610c2c8df0f6ceab0e1968f563df74b173"
- integrity sha512-v7+LQFbqZKmd/Tvf5/j1Xlbq6jXL/4d+gUtm2TNX4QiEC3ELWADmGr2dGlUyLl6aKTuYfsN72vAsO5zmavYkEg==
- dependencies:
- "@types/node" ">=12.12.47"
-
-"@grpc/proto-loader@^0.5.1":
- version "0.5.6"
- resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.5.6.tgz#1dea4b8a6412b05e2d58514d507137b63a52a98d"
- integrity sha512-DT14xgw3PSzPxwS13auTEwxhMMOoz33DPUKNtmYK/QYbBSpLXJy78FGGs5yVoxVobEqPm4iW9MOIoz0A3bLTRQ==
- dependencies:
- lodash.camelcase "^4.3.0"
- protobufjs "^6.8.6"
-
-"@grpc/proto-loader@^0.6.1":
- version "0.6.4"
- resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.6.4.tgz#5438c0d771e92274e77e631babdc14456441cbdc"
- integrity sha512-7xvDvW/vJEcmLUltCUGOgWRPM8Oofv0eCFSVMuKqaqWJaXSzmB+m9hiyqe34QofAl4WAzIKUZZlinIF9FOHyTQ==
- dependencies:
- "@types/long" "^4.0.1"
- lodash.camelcase "^4.3.0"
- long "^4.0.0"
- protobufjs "^6.10.0"
- yargs "^16.1.1"
-
-"@jsdevtools/ono@^7.1.3":
- version "7.1.3"
- resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796"
- integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==
-
-"@npmcli/move-file@^1.0.1":
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.1.2.tgz#1a82c3e372f7cae9253eb66d72543d6b8685c674"
- integrity sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==
- dependencies:
- mkdirp "^1.0.4"
- rimraf "^3.0.2"
-
-"@panva/asn1.js@^1.0.0":
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/@panva/asn1.js/-/asn1.js-1.0.0.tgz#dd55ae7b8129e02049f009408b97c61ccf9032f6"
- integrity sha512-UdkG3mLEqXgnlKsWanWcgb6dOjUzJ+XC5f+aWw30qrtjxeNUSfKX1cd5FBzOaXQumoe9nIqeZUvrRJS03HCCtw==
-
-"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2":
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf"
- integrity sha1-m4sMxmPWaafY9vXQiToU00jzD78=
-
-"@protobufjs/base64@^1.1.2":
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735"
- integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==
-
-"@protobufjs/codegen@^2.0.4":
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb"
- integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==
-
-"@protobufjs/eventemitter@^1.1.0":
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70"
- integrity sha1-NVy8mLr61ZePntCV85diHx0Ga3A=
-
-"@protobufjs/fetch@^1.1.0":
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45"
- integrity sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=
- dependencies:
- "@protobufjs/aspromise" "^1.1.1"
- "@protobufjs/inquire" "^1.1.0"
-
-"@protobufjs/float@^1.0.2":
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1"
- integrity sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=
-
-"@protobufjs/inquire@^1.1.0":
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089"
- integrity sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=
-
-"@protobufjs/path@^1.1.2":
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d"
- integrity sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=
-
-"@protobufjs/pool@^1.1.0":
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54"
- integrity sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=
-
-"@protobufjs/utf8@^1.1.0":
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
- integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=
-
-"@sindresorhus/is@^0.14.0":
- version "0.14.0"
- resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea"
- integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==
-
-"@szmarczak/http-timer@^1.1.2":
- version "1.1.2"
- 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.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
- integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==
-
-"@types/body-parser@*":
- version "1.19.1"
- resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.1.tgz#0c0174c42a7d017b818303d4b5d969cb0b75929c"
- integrity sha512-a6bTJ21vFOGIkwM0kzh9Yr89ziVxq4vYH2fQ6N8AeipEzai/cFK6aGMArIkUeIdRIgpwQa+2bXiLuUJCpSf2Cg==
- dependencies:
- "@types/connect" "*"
- "@types/node" "*"
-
-"@types/connect@*":
- version "3.4.35"
- resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1"
- integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==
- dependencies:
- "@types/node" "*"
-
-"@types/duplexify@^3.6.0":
- version "3.6.0"
- resolved "https://registry.yarnpkg.com/@types/duplexify/-/duplexify-3.6.0.tgz#dfc82b64bd3a2168f5bd26444af165bf0237dcd8"
- integrity sha512-5zOA53RUlzN74bvrSGwjudssD9F3a797sDZQkiYpUOxW+WHaXTCPz4/d5Dgi6FKnOqZ2CpaTo0DhgIfsXAOE/A==
- dependencies:
- "@types/node" "*"
-
-"@types/express-jwt@0.0.42":
- version "0.0.42"
- resolved "https://registry.yarnpkg.com/@types/express-jwt/-/express-jwt-0.0.42.tgz#4f04e1fadf9d18725950dc041808a4a4adf7f5ae"
- integrity sha512-WszgUddvM1t5dPpJ3LhWNH8kfNN8GPIBrAGxgIYXVCEGx6Bx4A036aAuf/r5WH9DIEdlmp7gHOYvSM6U87B0ag==
- dependencies:
- "@types/express" "*"
- "@types/express-unless" "*"
-
-"@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.18":
- version "4.17.24"
- resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.24.tgz#ea41f93bf7e0d59cd5a76665068ed6aab6815c07"
- integrity sha512-3UJuW+Qxhzwjq3xhwXm2onQcFHn76frIYVbTu+kn24LFxI+dEhdfISDFovPB8VpEgW8oQCTpRuCe+0zJxB7NEA==
- dependencies:
- "@types/node" "*"
- "@types/qs" "*"
- "@types/range-parser" "*"
-
-"@types/express-unless@*":
- version "0.5.2"
- resolved "https://registry.yarnpkg.com/@types/express-unless/-/express-unless-0.5.2.tgz#07e29883d280778588644b03563d8796f870f20e"
- integrity sha512-Q74UyYRX/zIgl1HSp9tUX2PlG8glkVm+59r7aK4KGKzC5jqKIOX6rrVLRQrzpZUQ84VukHtRoeAuon2nIssHPQ==
- dependencies:
- "@types/express" "*"
-
-"@types/express@*":
- version "4.17.13"
- resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034"
- integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==
- dependencies:
- "@types/body-parser" "*"
- "@types/express-serve-static-core" "^4.17.18"
- "@types/qs" "*"
- "@types/serve-static" "*"
-
-"@types/express@4.17.3":
- version "4.17.3"
- resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.3.tgz#38e4458ce2067873b09a73908df488870c303bd9"
- integrity sha512-I8cGRJj3pyOLs/HndoP+25vOqhqWkAZsWMEmq1qXy/b/M3ppufecUwaK2/TVDVxcV61/iSdhykUjQQ2DLSrTdg==
- dependencies:
- "@types/body-parser" "*"
- "@types/express-serve-static-core" "*"
- "@types/serve-static" "*"
-
-"@types/fs-extra@^8.0.1":
- version "8.1.2"
- resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-8.1.2.tgz#7125cc2e4bdd9bd2fc83005ffdb1d0ba00cca61f"
- integrity sha512-SvSrYXfWSc7R4eqnOzbQF4TZmfpNSM9FrSWLU3EUnWBuyZqNBOrv1B1JA3byUDPUl9z4Ab3jeZG2eDdySlgNMg==
- dependencies:
- "@types/node" "*"
-
-"@types/json-schema@^7.0.6":
- version "7.0.8"
- resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.8.tgz#edf1bf1dbf4e04413ca8e5b17b3b7d7d54b59818"
- integrity sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg==
-
-"@types/long@^4.0.0", "@types/long@^4.0.1":
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9"
- integrity sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==
-
-"@types/mime@^1":
- version "1.3.2"
- resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a"
- integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==
-
-"@types/minimatch@^3.0.3":
- version "3.0.5"
- resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40"
- integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==
-
-"@types/node@*", "@types/node@>=12.12.47", "@types/node@>=13.7.0":
- version "16.4.3"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-16.4.3.tgz#c01c1a215721f6dec71b47d88b4687463601ba48"
- integrity sha512-GKM4FLMkWDc0sfx7tXqPWkM6NBow1kge0fgQh0bOnlqo4iT1kvTvMEKE0c1RtUGnbLlGRXiAA8SumE//90uKAg==
-
-"@types/parse-json@^4.0.0":
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
- integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==
-
-"@types/qs@*":
- version "6.9.7"
- resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb"
- integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==
-
-"@types/range-parser@*":
- version "1.2.4"
- resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc"
- integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==
-
-"@types/serve-static@*":
- version "1.13.10"
- resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.10.tgz#f5e0ce8797d2d7cc5ebeda48a52c96c4fa47a8d9"
- integrity sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==
- dependencies:
- "@types/mime" "^1"
- "@types/node" "*"
-
-JSONStream@^1.2.1:
- version "1.3.5"
- resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0"
- integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==
- dependencies:
- jsonparse "^1.2.0"
- through ">=2.2.7 <3"
-
-abbrev@1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
- integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
-
-abort-controller@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
- integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==
- dependencies:
- event-target-shim "^5.0.0"
-
-accepts@~1.3.5, accepts@~1.3.7:
- version "1.3.7"
- resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
- integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==
- dependencies:
- mime-types "~2.1.24"
- negotiator "0.6.2"
-
-agent-base@6, agent-base@^6.0.2:
- version "6.0.2"
- resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
- integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
- dependencies:
- debug "4"
-
-agentkeepalive@^4.1.3:
- version "4.1.4"
- resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.1.4.tgz#d928028a4862cb11718e55227872e842a44c945b"
- integrity sha512-+V/rGa3EuU74H6wR04plBb7Ks10FbtUQgRj/FQOG7uUIEuaINI+AiqJR1k6t3SVNs7o7ZjIdus6706qqzVq8jQ==
- dependencies:
- debug "^4.1.0"
- depd "^1.1.2"
- humanize-ms "^1.2.1"
-
-aggregate-error@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a"
- integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==
- dependencies:
- clean-stack "^2.0.0"
- indent-string "^4.0.0"
-
-ajv@^6.12.2, ajv@^6.12.3:
- version "6.12.6"
- resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
- integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
- dependencies:
- fast-deep-equal "^3.1.1"
- fast-json-stable-stringify "^2.0.0"
- json-schema-traverse "^0.4.1"
- uri-js "^4.2.2"
-
-ansi-align@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.0.tgz#b536b371cf687caaef236c18d3e21fe3797467cb"
- integrity sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==
- dependencies:
- string-width "^3.0.0"
-
-ansi-escapes@^3.1.0, ansi-escapes@^3.2.0:
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b"
- integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==
-
-ansi-regex@^2.0.0, ansi-regex@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
- integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8=
-
-ansi-regex@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
- integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
-
-ansi-regex@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
- integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
-
-ansi-regex@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75"
- integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==
-
-ansi-styles@^2.2.1:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
- integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=
-
-ansi-styles@^3.2.1:
- version "3.2.1"
- resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
- integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
- dependencies:
- color-convert "^1.9.0"
-
-ansi-styles@^4.0.0, ansi-styles@^4.1.0:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
- integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
- dependencies:
- color-convert "^2.0.1"
-
-ansicolors@~0.3.2:
- version "0.3.2"
- resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979"
- integrity sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=
-
-anymatch@~3.1.2:
- version "3.1.2"
- 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.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
- integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==
-
-archiver-utils@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-2.1.0.tgz#e8a460e94b693c3e3da182a098ca6285ba9249e2"
- integrity sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==
- dependencies:
- glob "^7.1.4"
- graceful-fs "^4.2.0"
- lazystream "^1.0.0"
- lodash.defaults "^4.2.0"
- lodash.difference "^4.5.0"
- lodash.flatten "^4.4.0"
- lodash.isplainobject "^4.0.6"
- lodash.union "^4.6.0"
- normalize-path "^3.0.0"
- readable-stream "^2.0.0"
-
-archiver@^3.0.0:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/archiver/-/archiver-3.1.1.tgz#9db7819d4daf60aec10fe86b16cb9258ced66ea0"
- integrity sha512-5Hxxcig7gw5Jod/8Gq0OneVgLYET+oNHcxgWItq4TbhOzRLKNAFUb9edAftiMKXvXfCB0vbGrJdZDNq0dWMsxg==
- dependencies:
- archiver-utils "^2.1.0"
- async "^2.6.3"
- buffer-crc32 "^0.2.1"
- glob "^7.1.4"
- readable-stream "^3.4.0"
- tar-stream "^2.1.0"
- zip-stream "^2.1.2"
-
-are-we-there-yet@~1.1.2:
- version "1.1.5"
- resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21"
- integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==
- dependencies:
- delegates "^1.0.0"
- readable-stream "^2.0.6"
-
-arg@^4.1.0:
- version "4.1.3"
- 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.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.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
- integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
-
-array-differ@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-3.0.0.tgz#3cbb3d0f316810eafcc47624734237d6aee4ae6b"
- integrity sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==
-
-array-flatten@1.1.1, array-flatten@^1.0.0:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
- integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=
-
-array-flatten@3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-3.0.0.tgz#6428ca2ee52c7b823192ec600fa3ed2f157cd541"
- integrity sha512-zPMVc3ZYlGLNk4mpK1NzP2wg0ml9t7fUgDsayR5Y5rSzxQilzR9FGu/EH2jQOcKSAeAfWeylyW8juy3OkWRvNA==
-
-array-union@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
- integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
-
-arrify@^2.0.0, arrify@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa"
- integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==
-
-as-array@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/as-array/-/as-array-1.0.0.tgz#28a6eeeaa5729f1f4eca2047df5e9de1abda0ed1"
- integrity sha1-KKbu6qVynx9OyiBH316d4avaDtE=
- dependencies:
- lodash.isarguments "2.4.x"
- lodash.isobject "^2.4.1"
- lodash.values "^2.4.1"
-
-as-array@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/as-array/-/as-array-2.0.0.tgz#4f04805d87f8fce8e511bc2108f8e5e3a287d547"
- integrity sha1-TwSAXYf4/OjlEbwhCPjl46KH1Uc=
-
-asn1@~0.2.3:
- version "0.2.4"
- resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
- integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
- dependencies:
- safer-buffer "~2.1.0"
-
-assert-plus@1.0.0, assert-plus@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
- integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
-
-async-each@^1.0.1:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf"
- integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==
-
-async-retry@^1.3.1:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/async-retry/-/async-retry-1.3.1.tgz#139f31f8ddce50c0870b0ba558a6079684aaed55"
- integrity sha512-aiieFW/7h3hY0Bq5d+ktDBejxuwR78vRu9hDUdR8rNhSaQ29VzPL4AoIRG7D/c7tdenwOcKvgPM6tIxB3cB6HA==
- dependencies:
- retry "0.12.0"
-
-async@^1.3.0:
- version "1.5.2"
- resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
- integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=
-
-async@^2.6.2, async@^2.6.3:
- version "2.6.3"
- resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff"
- integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==
- dependencies:
- lodash "^4.17.14"
-
-async@^3.1.0:
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/async/-/async-3.2.0.tgz#b3a2685c5ebb641d3de02d161002c60fc9f85720"
- integrity sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==
-
-asynckit@^0.4.0:
- version "0.4.0"
- resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
- integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
-
-aws-sign2@~0.7.0:
- version "0.7.0"
- resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
- integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=
-
-aws4@^1.8.0:
- version "1.11.0"
- resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
- integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
-
-balanced-match@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
- integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
-
-base64-js@^1.3.0, base64-js@^1.3.1, base64-js@^1.5.1:
- version "1.5.1"
- resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
- integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
-
-basic-auth-connect@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz#fdb0b43962ca7b40456a7c2bb48fe173da2d2122"
- integrity sha1-/bC0OWLKe0BFanwrtI/hc9otISI=
-
-basic-auth@~2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.1.tgz#b998279bf47ce38344b4f3cf916d4679bbf51e3a"
- integrity sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==
- dependencies:
- safe-buffer "5.1.2"
-
-bcrypt-pbkdf@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
- integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
- dependencies:
- tweetnacl "^0.14.3"
-
-big-integer@^1.6.17:
- version "1.6.48"
- resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.48.tgz#8fd88bd1632cba4a1c8c3e3d7159f08bb95b4b9e"
- integrity sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==
-
-bignumber.js@^9.0.0:
- version "9.0.1"
- resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.1.tgz#8d7ba124c882bfd8e43260c67475518d0689e4e5"
- integrity sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==
-
-binary-extensions@^2.0.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
- integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
-
-binary@~0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/binary/-/binary-0.3.0.tgz#9f60553bc5ce8c3386f3b553cff47462adecaa79"
- integrity sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=
- dependencies:
- buffers "~0.1.1"
- chainsaw "~0.1.0"
-
-bl@^4.0.3:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a"
- integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==
- dependencies:
- buffer "^5.5.0"
- inherits "^2.0.4"
- readable-stream "^3.4.0"
-
-blakejs@^1.1.0:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.1.1.tgz#bf313053978b2cd4c444a48795710be05c785702"
- integrity sha512-bLG6PHOCZJKNshTjGRBvET0vTciwQE6zFKOKKXPDJfwFBd4Ac0yBfPZqcGvGJap50l7ktvlpFqc2jGVaUgbJgg==
-
-bluebird@~3.4.1:
- version "3.4.7"
- resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.7.tgz#f72d760be09b7f76d08ed8fae98b289a8d05fab3"
- integrity sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=
-
-body-parser@1.19.0, body-parser@^1.18.3, body-parser@^1.19.0:
- version "1.19.0"
- resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
- integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==
- dependencies:
- bytes "3.1.0"
- content-type "~1.0.4"
- debug "2.6.9"
- depd "~1.1.2"
- http-errors "1.7.2"
- iconv-lite "0.4.24"
- on-finished "~2.3.0"
- qs "6.7.0"
- raw-body "2.4.0"
- type-is "~1.6.17"
-
-boxen@^4.2.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/boxen/-/boxen-4.2.0.tgz#e411b62357d6d6d36587c8ac3d5d974daa070e64"
- integrity sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==
- 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"
-
-brace-expansion@^1.1.7:
- version "1.1.11"
- resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
- integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
- dependencies:
- balanced-match "^1.0.0"
- concat-map "0.0.1"
-
-braces@~3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
- integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
- dependencies:
- fill-range "^7.0.1"
-
-buffer-crc32@^0.2.1, buffer-crc32@^0.2.13:
- version "0.2.13"
- resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
- integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=
-
-buffer-equal-constant-time@1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
- integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=
-
-buffer-from@^1.0.0:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
- integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
-
-buffer-indexof-polyfill@~1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz#d2732135c5999c64b277fcf9b1abe3498254729c"
- integrity sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==
-
-buffer@^5.1.0, buffer@^5.5.0:
- version "5.7.1"
- 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"
-
-buffers@~0.1.1:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/buffers/-/buffers-0.1.1.tgz#b24579c3bed4d6d396aeee6d9a8ae7f5482ab7bb"
- integrity sha1-skV5w77U1tOWru5tmorn9Ugqt7s=
-
-builtin-modules@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
- integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=
-
-bytes@3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
- integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=
-
-bytes@3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
- integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
-
-cacache@^15.0.5:
- version "15.2.0"
- resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.2.0.tgz#73af75f77c58e72d8c630a7a2858cb18ef523389"
- integrity sha512-uKoJSHmnrqXgthDFx/IU6ED/5xd+NNGe+Bb+kLZy7Ku4P+BaiWEUflAKPZ7eAzsYGcsAGASJZsybXp+quEcHTw==
- dependencies:
- "@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"
-
-cacheable-request@^6.0.0:
- version "6.1.0"
- 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"
- 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"
-
-call-bind@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
- integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==
- dependencies:
- function-bind "^1.1.1"
- get-intrinsic "^1.0.2"
-
-call-me-maybe@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b"
- integrity sha1-JtII6onje1y95gJQoV8DHBak1ms=
-
-callsites@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
- integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
-
-camelcase@^5.3.1:
- version "5.3.1"
- resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
- integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
-
-cardinal@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/cardinal/-/cardinal-2.1.1.tgz#7cc1055d822d212954d07b085dea251cc7bc5505"
- integrity sha1-fMEFXYItISlU0HsIXeolHMe8VQU=
- dependencies:
- ansicolors "~0.3.2"
- redeyed "~2.1.0"
-
-caseless@~0.12.0:
- version "0.12.0"
- resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
- integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
-
-chainsaw@~0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/chainsaw/-/chainsaw-0.1.0.tgz#5eab50b28afe58074d0d58291388828b5e5fbc98"
- integrity sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=
- dependencies:
- traverse ">=0.3.0 <0.4"
-
-chalk@^1.1.3:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
- integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=
- dependencies:
- 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"
-
-chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2:
- version "2.4.2"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
- integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
- dependencies:
- ansi-styles "^3.2.1"
- escape-string-regexp "^1.0.5"
- supports-color "^5.3.0"
-
-chalk@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4"
- integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==
- dependencies:
- ansi-styles "^4.1.0"
- supports-color "^7.1.0"
-
-chalk@^4.0.0:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.1.tgz#c80b3fab28bf6371e6863325eee67e618b77e6ad"
- integrity sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==
- dependencies:
- ansi-styles "^4.1.0"
- supports-color "^7.1.0"
-
-chardet@^0.7.0:
- version "0.7.0"
- resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
- integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
-
-chokidar@^3.0.2:
- version "3.5.2"
- resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75"
- integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==
- 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"
- optionalDependencies:
- fsevents "~2.3.2"
-
-chownr@^1.1.1:
- version "1.1.4"
- 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.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.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46"
- integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==
-
-cjson@^0.3.1:
- version "0.3.3"
- resolved "https://registry.yarnpkg.com/cjson/-/cjson-0.3.3.tgz#a92d9c786e5bf9b930806329ee05d5d3261b4afa"
- integrity sha1-qS2ceG5b+bkwgGMp7gXV0yYbSvo=
- dependencies:
- json-parse-helpfulerror "^1.0.3"
-
-clean-stack@^2.0.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b"
- integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==
-
-cli-boxes@^2.2.0:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f"
- integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==
-
-cli-color@^1.2.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/cli-color/-/cli-color-1.4.0.tgz#7d10738f48526824f8fe7da51857cb0f572fe01f"
- integrity sha512-xu6RvQqqrWEo6MPR1eixqGPywhYBHRs653F9jfXB2Hx4jdM/3WxiNE1vppRmxtMIfl16SFYTpYlrnqH/HsK/2w==
- dependencies:
- ansi-regex "^2.1.1"
- d "1"
- es5-ext "^0.10.46"
- es6-iterator "^2.0.3"
- memoizee "^0.4.14"
- timers-ext "^0.1.5"
-
-cli-cursor@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
- integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=
- dependencies:
- restore-cursor "^2.0.0"
-
-cli-spinners@^2.0.0:
- version "2.6.0"
- resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.6.0.tgz#36c7dc98fb6a9a76bd6238ec3f77e2425627e939"
- integrity sha512-t+4/y50K/+4xcCRosKkA7W4gTr1MySvLV0q+PxmG7FJ5g+66ChKurYjxBCjHggHH3HA5Hh9cy+lcUGWDqVH+4Q==
-
-cli-table@^0.3.1:
- version "0.3.6"
- resolved "https://registry.yarnpkg.com/cli-table/-/cli-table-0.3.6.tgz#e9d6aa859c7fe636981fd3787378c2a20bce92fc"
- integrity sha512-ZkNZbnZjKERTY5NwC2SeMeLeifSPq/pubeRoTpdr3WchLlnZg6hEgvHkK5zL7KNFdd9PmHN8lxrENUwI3cE8vQ==
- dependencies:
- colors "1.0.3"
-
-cli-width@^2.0.0:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48"
- integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==
-
-cliui@^7.0.2:
- version "7.0.4"
- 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"
- strip-ansi "^6.0.0"
- wrap-ansi "^7.0.0"
-
-clone-response@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b"
- integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=
- dependencies:
- mimic-response "^1.0.0"
-
-clone@^1.0.2:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
- integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4=
-
-code-point-at@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
- integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
-
-color-convert@^1.9.0, color-convert@^1.9.1:
- version "1.9.3"
- resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
- integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
- dependencies:
- color-name "1.1.3"
-
-color-convert@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
- integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
- dependencies:
- color-name "~1.1.4"
-
-color-name@1.1.3:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
- integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
-
-color-name@^1.0.0, color-name@~1.1.4:
- version "1.1.4"
- resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
- integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
-
-color-string@^1.5.2:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.6.0.tgz#c3915f61fe267672cb7e1e064c9d692219f6c312"
- integrity sha512-c/hGS+kRWJutUBEngKKmk4iH3sD59MBkoxVapS/0wgpCz2u7XsNloxknyvBhzwEs1IbV36D9PwqLPJ2DTu3vMA==
- dependencies:
- color-name "^1.0.0"
- simple-swizzle "^0.2.2"
-
-color@3.0.x:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/color/-/color-3.0.0.tgz#d920b4328d534a3ac8295d68f7bd4ba6c427be9a"
- integrity sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==
- dependencies:
- color-convert "^1.9.1"
- color-string "^1.5.2"
-
-colors@1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b"
- integrity sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=
-
-colors@^1.2.1:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
- integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==
-
-colorspace@1.1.x:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.2.tgz#e0128950d082b86a2168580796a0aa5d6c68d8c5"
- integrity sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==
- dependencies:
- color "3.0.x"
- text-hex "1.0.x"
-
-combined-stream@^1.0.6, combined-stream@~1.0.6:
- version "1.0.8"
- 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.12.1:
- 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==
-
-commander@^4.0.1:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068"
- integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==
-
-compare-semver@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/compare-semver/-/compare-semver-1.1.0.tgz#7c0a79a27bb80b6c6994445f82958259d3d02153"
- integrity sha1-fAp5onu4C2xplERfgpWCWdPQIVM=
- dependencies:
- semver "^5.0.1"
-
-compare-versions@^3.6.0:
- version "3.6.0"
- resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.6.0.tgz#1a5689913685e5a87637b8d3ffca75514ec41d62"
- integrity sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==
-
-compress-commons@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-2.1.1.tgz#9410d9a534cf8435e3fbbb7c6ce48de2dc2f0610"
- integrity sha512-eVw6n7CnEMFzc3duyFVrQEuY1BlHR3rYsSztyG32ibGMW722i3C6IizEGMFmfMU+A+fALvBIwxN3czffTcdA+Q==
- dependencies:
- buffer-crc32 "^0.2.13"
- crc32-stream "^3.0.1"
- normalize-path "^3.0.0"
- readable-stream "^2.3.6"
-
-compressible@^2.0.12, compressible@~2.0.16:
- version "2.0.18"
- resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba"
- integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==
- dependencies:
- mime-db ">= 1.43.0 < 2"
-
-compression@^1.7.0:
- version "1.7.4"
- resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f"
- integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==
- dependencies:
- 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"
-
-concat-map@0.0.1:
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
- integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
-
-configstore@^5.0.0, configstore@^5.0.1:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96"
- integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==
- 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"
-
-connect@^3.6.2:
- version "3.7.0"
- resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8"
- integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==
- dependencies:
- debug "2.6.9"
- finalhandler "1.1.2"
- parseurl "~1.3.3"
- utils-merge "1.0.1"
-
-console-control-strings@^1.0.0, console-control-strings@~1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
- integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=
-
-content-disposition@0.5.3:
- version "0.5.3"
- resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd"
- integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==
- dependencies:
- safe-buffer "5.1.2"
-
-content-type@^1.0.4, content-type@~1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
- integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
-
-cookie-signature@1.0.6:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
- integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw=
-
-cookie@0.4.0:
- version "0.4.0"
- resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba"
- integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==
-
-core-util-is@1.0.2, core-util-is@~1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
- integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
-
-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"
-
-cosmiconfig@^7.0.0:
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.0.tgz#ef9b44d773959cae63ddecd122de23853b60f8d3"
- integrity sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==
- dependencies:
- "@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"
-
-crc32-stream@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-3.0.1.tgz#cae6eeed003b0e44d739d279de5ae63b171b4e85"
- integrity sha512-mctvpXlbzsvK+6z8kJwSJ5crm7yBwrQMTybJzMw1O4lLGJqjlDCXY2Zw7KheiA6XBEcBmfLx1D88mjRGVJtY9w==
- dependencies:
- crc "^3.4.4"
- readable-stream "^3.4.0"
-
-crc@^3.4.4:
- version "3.8.0"
- resolved "https://registry.yarnpkg.com/crc/-/crc-3.8.0.tgz#ad60269c2c856f8c299e2c4cc0de4556914056c6"
- integrity sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==
- dependencies:
- buffer "^5.1.0"
-
-cross-env@^5.1.3:
- version "5.2.1"
- resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-5.2.1.tgz#b2c76c1ca7add66dc874d11798466094f551b34d"
- integrity sha512-1yHhtcfAd1r4nwQgknowuUNfIT9E8dOMMspC36g45dN+iD1blloi7xp8X/xAIDnjHWyt1uQ8PHk2fkNaym7soQ==
- dependencies:
- cross-spawn "^6.0.5"
-
-cross-spawn@^6.0.5:
- version "6.0.5"
- resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
- integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
- dependencies:
- nice-try "^1.0.4"
- path-key "^2.0.1"
- semver "^5.5.0"
- shebang-command "^1.2.0"
- which "^1.2.9"
-
-cross-spawn@^7.0.0, cross-spawn@^7.0.1:
- version "7.0.3"
- resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
- integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
- dependencies:
- path-key "^3.1.0"
- shebang-command "^2.0.0"
- which "^2.0.1"
-
-crypto-random-string@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5"
- integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==
-
-csv-streamify@^3.0.4:
- version "3.0.4"
- resolved "https://registry.yarnpkg.com/csv-streamify/-/csv-streamify-3.0.4.tgz#4cb614c57e3f299cca17b63fdcb4ad167777f47a"
- integrity sha1-TLYUxX4/KZzKF7Y/3LStFnd39Ho=
- dependencies:
- through2 "2.0.1"
-
-d@1, d@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a"
- integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==
- dependencies:
- es5-ext "^0.10.50"
- type "^1.0.1"
-
-dashdash@^1.12.0:
- version "1.14.1"
- resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
- integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=
- dependencies:
- assert-plus "^1.0.0"
-
-date-and-time@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/date-and-time/-/date-and-time-1.0.1.tgz#4959b7faf1ec5873e59d926d4528b9223a808a57"
- integrity sha512-7u+uNfnjWkX+YFQfivvW24TjaJG6ahvTrfw1auq7KlC7osuGcZBIWGBvB9UcENjH6JnLVhMqlRripk1dSHjAUA==
-
-debug@2.6.9:
- version "2.6.9"
- resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
- integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
- dependencies:
- ms "2.0.0"
-
-debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2:
- version "4.3.2"
- resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b"
- integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==
- dependencies:
- ms "2.1.2"
-
-debug@4.3.1:
- version "4.3.1"
- resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee"
- integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==
- dependencies:
- ms "2.1.2"
-
-debug@^3.1.1:
- 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"
-
-decompress-response@^3.3.0:
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3"
- integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=
- dependencies:
- mimic-response "^1.0.0"
-
-deep-extend@^0.6.0:
- version "0.6.0"
- resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
- integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
-
-deep-freeze@0.0.1:
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/deep-freeze/-/deep-freeze-0.0.1.tgz#3a0b0005de18672819dfd38cd31f91179c893e84"
- integrity sha1-OgsABd4YZygZ39OM0x+RF5yJPoQ=
-
-deep-is@^0.1.3:
- version "0.1.3"
- resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
- integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
-
-defaults@^1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d"
- integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=
- dependencies:
- clone "^1.0.2"
-
-defer-to-connect@^1.0.1:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591"
- integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==
-
-delayed-stream@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
- integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
-
-delegates@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
- integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=
-
-depd@^1.1.2, depd@~1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
- integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
-
-depd@~2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
- integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
-
-destroy@^1.0.4, destroy@~1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
- integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
-
-dicer@^0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/dicer/-/dicer-0.3.0.tgz#eacd98b3bfbf92e8ab5c2fdb71aaac44bb06b872"
- integrity sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA==
- dependencies:
- streamsearch "0.1.2"
-
-diff@^4.0.1:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
- integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
-
-dot-prop@^5.2.0:
- version "5.3.0"
- resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88"
- integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==
- dependencies:
- is-obj "^2.0.0"
-
-dotenv@^6.1.0:
- version "6.2.0"
- resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-6.2.0.tgz#941c0410535d942c8becf28d3f357dbd9d476064"
- integrity sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w==
-
-duplexer2@~0.1.4:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1"
- integrity sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=
- dependencies:
- readable-stream "^2.0.2"
-
-duplexer3@^0.1.4:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
- integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=
-
-duplexify@^3.6.0:
- version "3.7.1"
- resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309"
- integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==
- dependencies:
- end-of-stream "^1.0.0"
- inherits "^2.0.1"
- readable-stream "^2.0.0"
- stream-shift "^1.0.0"
-
-duplexify@^4.0.0, duplexify@^4.1.1:
- version "4.1.2"
- resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.2.tgz#18b4f8d28289132fa0b9573c898d9f903f81c7b0"
- integrity sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==
- dependencies:
- end-of-stream "^1.4.1"
- inherits "^2.0.3"
- readable-stream "^3.1.1"
- stream-shift "^1.0.0"
-
-ecc-jsbn@~0.1.1:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
- integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=
- dependencies:
- jsbn "~0.1.0"
- safer-buffer "^2.1.0"
-
-ecdsa-sig-formatter@1.0.11, ecdsa-sig-formatter@^1.0.11:
- version "1.0.11"
- 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"
-
-ee-first@1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
- integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
-
-emoji-regex@^7.0.1:
- version "7.0.3"
- resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
- integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==
-
-emoji-regex@^8.0.0:
- version "8.0.0"
- resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
- integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
-
-enabled@2.0.x:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2"
- integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==
-
-encodeurl@~1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
- integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
-
-encoding@^0.1.12:
- version "0.1.13"
- resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9"
- integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==
- dependencies:
- iconv-lite "^0.6.2"
-
-end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1:
- version "1.4.4"
- resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
- integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
- dependencies:
- once "^1.4.0"
-
-ent@^2.2.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d"
- integrity sha1-6WQhkyWiHQX0RGai9obtbOX13R0=
-
-env-paths@^2.2.0:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2"
- integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==
-
-err-code@^2.0.2:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9"
- integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==
-
-error-ex@^1.3.1:
- version "1.3.2"
- resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
- integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
- dependencies:
- is-arrayish "^0.2.1"
-
-es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@^0.10.53, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46:
- version "0.10.53"
- resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1"
- integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==
- dependencies:
- es6-iterator "~2.0.3"
- es6-symbol "~3.1.3"
- next-tick "~1.0.0"
-
-es6-iterator@^2.0.3, es6-iterator@~2.0.3:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7"
- integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c=
- dependencies:
- d "1"
- es5-ext "^0.10.35"
- es6-symbol "^3.1.1"
-
-es6-symbol@^3.1.1, es6-symbol@~3.1.3:
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18"
- integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==
- dependencies:
- d "^1.0.1"
- ext "^1.1.2"
-
-es6-weak-map@^2.0.3:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.3.tgz#b6da1f16cc2cc0d9be43e6bdbfc5e7dfcdf31d53"
- integrity sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==
- dependencies:
- d "1"
- es5-ext "^0.10.46"
- es6-iterator "^2.0.3"
- es6-symbol "^3.1.1"
-
-escalade@^3.1.1:
- version "3.1.1"
- 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.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.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
- integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=
-
-escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
- integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
-
-esprima@^4.0.0, esprima@~4.0.0:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
- integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
-
-etag@~1.8.1:
- version "1.8.1"
- resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
- integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
-
-event-emitter@^0.3.5:
- version "0.3.5"
- resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39"
- integrity sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=
- dependencies:
- d "1"
- es5-ext "~0.10.14"
-
-event-target-shim@^5.0.0:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789"
- integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==
-
-events-listener@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/events-listener/-/events-listener-1.1.0.tgz#dd49b4628480eba58fde31b870ee346b3990b349"
- integrity sha512-Kd3EgYfODHueq6GzVfs/VUolh2EgJsS8hkO3KpnDrxVjU3eq63eXM2ujXkhPP+OkeUOhL8CxdfZbQXzryb5C4g==
-
-execa@^4.0.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a"
- integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==
- 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"
-
-exegesis-express@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/exegesis-express/-/exegesis-express-2.0.1.tgz#f162cdd68ee93dc14d832b02b1dbeab053697ee9"
- integrity sha512-8ORl1YRygYGPdR+zcClMqzaU+JQuvdNIw/s0RNwYluxNecEHkDEcXFmO6A5T79p7e48KI8iXJYt6KIn4Z9z4bg==
- dependencies:
- exegesis "^2.5.7"
-
-exegesis@^2.5.7:
- version "2.5.7"
- resolved "https://registry.yarnpkg.com/exegesis/-/exegesis-2.5.7.tgz#232c4b01361bc2bf0d9d4c07549c479e77f2b7a3"
- integrity sha512-Y0gEY3hgoLa80aMUm8rhhlIW3/KWo4uqN5hKJqok2GLh3maZjRLRC+p0gj33Jw3upAOKOXeRgScT5rtRoMyxwQ==
- dependencies:
- "@apidevtools/json-schema-ref-parser" "^9.0.3"
- ajv "^6.12.2"
- body-parser "^1.18.3"
- content-type "^1.0.4"
- deep-freeze "0.0.1"
- events-listener "^1.1.0"
- glob "^7.1.3"
- json-ptr "^2.2.0"
- json-schema-traverse "^1.0.0"
- lodash "^4.17.11"
- openapi3-ts "^2.0.1"
- promise-breaker "^5.0.0"
- pump "^3.0.0"
- qs "^6.6.0"
- raw-body "^2.3.3"
- semver "^7.0.0"
-
-exit-code@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/exit-code/-/exit-code-1.0.2.tgz#ce165811c9f117af6a5f882940b96ae7f9aecc34"
- integrity sha1-zhZYEcnxF69qX4gpQLlq5/muzDQ=
-
-express@^4.16.4, express@^4.17.1:
- version "4.17.1"
- resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134"
- integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==
- dependencies:
- accepts "~1.3.7"
- array-flatten "1.1.1"
- body-parser "1.19.0"
- content-disposition "0.5.3"
- content-type "~1.0.4"
- cookie "0.4.0"
- cookie-signature "1.0.6"
- debug "2.6.9"
- depd "~1.1.2"
- encodeurl "~1.0.2"
- escape-html "~1.0.3"
- etag "~1.8.1"
- finalhandler "~1.1.2"
- fresh "0.5.2"
- merge-descriptors "1.0.1"
- methods "~1.1.2"
- on-finished "~2.3.0"
- parseurl "~1.3.3"
- path-to-regexp "0.1.7"
- proxy-addr "~2.0.5"
- qs "6.7.0"
- range-parser "~1.2.1"
- safe-buffer "5.1.2"
- send "0.17.1"
- serve-static "1.14.1"
- setprototypeof "1.1.1"
- statuses "~1.5.0"
- type-is "~1.6.18"
- utils-merge "1.0.1"
- vary "~1.1.2"
-
-ext@^1.1.2:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/ext/-/ext-1.4.0.tgz#89ae7a07158f79d35517882904324077e4379244"
- integrity sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==
- dependencies:
- type "^2.0.0"
-
-extend@^3.0.2, extend@~3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
- integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
-
-external-editor@^3.0.3:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495"
- integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==
- dependencies:
- chardet "^0.7.0"
- iconv-lite "^0.4.24"
- tmp "^0.0.33"
-
-extsprintf@1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
- integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=
-
-extsprintf@^1.2.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
- integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
-
-fast-deep-equal@^3.1.1:
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
- integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
-
-fast-json-stable-stringify@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
- integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
-
-fast-safe-stringify@^2.0.4:
- version "2.0.8"
- resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.8.tgz#dc2af48c46cf712b683e849b2bbd446b32de936f"
- integrity sha512-lXatBjf3WPjmWD6DpIZxkeSsCOwqI0maYMpgDlx8g4U2qi4lbjA9oH/HD2a87G+KfsUmo5WbJFmqBZlPxtptag==
-
-fast-text-encoding@^1.0.0, fast-text-encoding@^1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz#ec02ac8e01ab8a319af182dae2681213cfe9ce53"
- integrity sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig==
-
-fast-url-parser@^1.1.3:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d"
- integrity sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0=
- dependencies:
- punycode "^1.3.2"
-
-faye-websocket@0.11.3:
- version "0.11.3"
- resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.3.tgz#5c0e9a8968e8912c286639fde977a8b209f2508e"
- integrity sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==
- dependencies:
- websocket-driver ">=0.5.1"
-
-fecha@^4.2.0:
- version "4.2.1"
- resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.1.tgz#0a83ad8f86ef62a091e22bb5a039cd03d23eecce"
- integrity sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q==
-
-figures@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962"
- integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=
- dependencies:
- escape-string-regexp "^1.0.5"
-
-filesize@^3.1.3:
- version "3.6.1"
- resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317"
- integrity sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==
-
-fill-range@^7.0.1:
- version "7.0.1"
- 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"
-
-finalhandler@1.1.2, finalhandler@~1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d"
- integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==
- dependencies:
- debug "2.6.9"
- encodeurl "~1.0.2"
- escape-html "~1.0.3"
- on-finished "~2.3.0"
- parseurl "~1.3.3"
- statuses "~1.5.0"
- unpipe "~1.0.0"
-
-find-up@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
- integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
- dependencies:
- locate-path "^5.0.0"
- path-exists "^4.0.0"
-
-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"
-
-find-versions@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/find-versions/-/find-versions-4.0.0.tgz#3c57e573bf97769b8cb8df16934b627915da4965"
- integrity sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==
- dependencies:
- semver-regex "^3.1.2"
-
-firebase-admin@^9.11.0:
- version "9.11.0"
- resolved "https://registry.yarnpkg.com/firebase-admin/-/firebase-admin-9.11.0.tgz#c0c72e4480b836fb4cd15e6d834ddfbfb9cc54ba"
- integrity sha512-68fXdwcKF99LkWBE33M5hnLwjvGpbCRznIOtZVsiBqZdM9iwxlTfNEpAckh++o3GdJcSLRUWmIN+MKqPUsxoCA==
- dependencies:
- "@firebase/database" "^0.10.0"
- "@firebase/database-types" "^0.7.2"
- "@types/node" ">=12.12.47"
- dicer "^0.3.0"
- jsonwebtoken "^8.5.1"
- jwks-rsa "^2.0.2"
- node-forge "^0.10.0"
- optionalDependencies:
- "@google-cloud/firestore" "^4.5.0"
- "@google-cloud/storage" "^5.3.0"
-
-firebase-functions@^3.14.1:
- version "3.14.1"
- resolved "https://registry.yarnpkg.com/firebase-functions/-/firebase-functions-3.14.1.tgz#3ac5bc70989365874f41d06bca3b42a233dd6039"
- integrity sha512-hL/qm+i5i1qKYmAFMlQ4mwRngDkP+3YT3F4E4Nd5Hj2QKeawBdZiMGgEt6zqTx08Zq04vHiSnSM0z75UJRSg6Q==
- dependencies:
- "@types/express" "4.17.3"
- cors "^2.8.5"
- express "^4.17.1"
- lodash "^4.17.14"
-
-firebase-tools@^8.7.0:
- version "8.20.0"
- resolved "https://registry.yarnpkg.com/firebase-tools/-/firebase-tools-8.20.0.tgz#0c7b69a611f584c44ca4cbf9e3003b18ebfd17be"
- integrity sha512-FovOHkPEvdT31EqxDzjJkaJIYLrc+0GZwQ3ixT1WI3yF3o4TG8MCVo+QidmcNqyX0XZnI3/5sF3dpxXQ/HzaVw==
- dependencies:
- "@google-cloud/pubsub" "^1.7.0"
- JSONStream "^1.2.1"
- abort-controller "^3.0.0"
- archiver "^3.0.0"
- body-parser "^1.19.0"
- chokidar "^3.0.2"
- cjson "^0.3.1"
- cli-color "^1.2.0"
- cli-table "^0.3.1"
- commander "^4.0.1"
- configstore "^5.0.1"
- cross-env "^5.1.3"
- cross-spawn "^7.0.1"
- csv-streamify "^3.0.4"
- dotenv "^6.1.0"
- exegesis-express "^2.0.0"
- exit-code "^1.0.2"
- express "^4.16.4"
- filesize "^3.1.3"
- fs-extra "^0.23.1"
- glob "^7.1.2"
- google-auth-library "^5.5.0"
- google-gax "~1.12.0"
- inquirer "~6.3.1"
- js-yaml "^3.13.1"
- jsonschema "^1.0.2"
- jsonwebtoken "^8.2.1"
- leven "^3.1.0"
- lodash "^4.17.19"
- marked "^0.7.0"
- marked-terminal "^3.3.0"
- minimatch "^3.0.4"
- morgan "^1.10.0"
- node-fetch "^2.6.1"
- open "^6.3.0"
- ora "^3.4.0"
- plist "^3.0.1"
- portfinder "^1.0.23"
- progress "^2.0.3"
- request "^2.87.0"
- rimraf "^3.0.0"
- semver "^5.7.1"
- superstatic "^7.1.0"
- tar "^4.3.0"
- tcp-port-used "^1.0.1"
- tmp "0.0.33"
- triple-beam "^1.3.0"
- tweetsodium "0.0.5"
- universal-analytics "^0.4.16"
- unzipper "^0.10.10"
- update-notifier "^4.1.0"
- uuid "^3.0.0"
- winston "^3.0.0"
- ws "^7.2.3"
-
-flat-arguments@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/flat-arguments/-/flat-arguments-1.0.2.tgz#9baa780adf0501f282d726c9c6a038dba44ea76f"
- integrity sha1-m6p4Ct8FAfKC1ybJxqA426ROp28=
- dependencies:
- array-flatten "^1.0.0"
- as-array "^1.0.0"
- lodash.isarguments "^3.0.0"
- lodash.isobject "^3.0.0"
-
-fn.name@1.x.x:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc"
- integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==
-
-forever-agent@~0.6.1:
- version "0.6.1"
- resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
- integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
-
-form-data@~2.3.2:
- version "2.3.3"
- resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
- integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==
- dependencies:
- asynckit "^0.4.0"
- combined-stream "^1.0.6"
- mime-types "^2.1.12"
-
-forwarded@0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
- integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==
-
-fresh@0.5.2:
- version "0.5.2"
- resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
- integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=
-
-fs-constants@^1.0.0:
- version "1.0.0"
- 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@^0.23.1:
- version "0.23.1"
- resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.23.1.tgz#6611dba6adf2ab8dc9c69fab37cddf8818157e3d"
- integrity sha1-ZhHbpq3yq43Jxp+rN83fiBgVfj0=
- dependencies:
- graceful-fs "^4.1.2"
- jsonfile "^2.1.0"
- path-is-absolute "^1.0.0"
- rimraf "^2.2.8"
-
-fs-extra@^8.1.0:
- version "8.1.0"
- resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0"
- integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==
- dependencies:
- graceful-fs "^4.2.0"
- jsonfile "^4.0.0"
- universalify "^0.1.0"
-
-fs-minipass@^1.2.5:
- version "1.2.7"
- resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7"
- integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==
- dependencies:
- minipass "^2.6.0"
-
-fs-minipass@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
- integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==
- dependencies:
- minipass "^3.0.0"
-
-fs.realpath@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
- integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
-
-fsevents@~2.3.2:
- version "2.3.2"
- resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
- integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
-
-fstream@^1.0.12:
- version "1.0.12"
- resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045"
- integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==
- dependencies:
- graceful-fs "^4.1.2"
- inherits "~2.0.0"
- mkdirp ">=0.5 0"
- rimraf "2"
-
-function-bind@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
- integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
-
-functional-red-black-tree@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
- integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=
-
-gauge@~2.7.3:
- version "2.7.4"
- resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
- 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"
-
-gaxios@^2.1.0:
- version "2.3.4"
- resolved "https://registry.yarnpkg.com/gaxios/-/gaxios-2.3.4.tgz#eea99353f341c270c5f3c29fc46b8ead56f0a173"
- integrity sha512-US8UMj8C5pRnao3Zykc4AAVr+cffoNKRTg9Rsf2GiuZCW69vgJj38VK2PzlPuQU73FZ/nTk9/Av6/JGcE1N9vA==
- dependencies:
- abort-controller "^3.0.0"
- extend "^3.0.2"
- https-proxy-agent "^5.0.0"
- is-stream "^2.0.0"
- node-fetch "^2.3.0"
-
-gaxios@^4.0.0:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/gaxios/-/gaxios-4.3.0.tgz#ad4814d89061f85b97ef52aed888c5dbec32f774"
- integrity sha512-pHplNbslpwCLMyII/lHPWFQbJWOX0B3R1hwBEOvzYi1GmdKZruuEHK4N9V6f7tf1EaPYyF80mui1+344p6SmLg==
- dependencies:
- abort-controller "^3.0.0"
- extend "^3.0.2"
- https-proxy-agent "^5.0.0"
- is-stream "^2.0.0"
- node-fetch "^2.3.0"
-
-gcp-metadata@^3.4.0:
- version "3.5.0"
- resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-3.5.0.tgz#6d28343f65a6bbf8449886a0c0e4a71c77577055"
- integrity sha512-ZQf+DLZ5aKcRpLzYUyBS3yo3N0JSa82lNDO8rj3nMSlovLcz2riKFBsYgDzeXcv75oo5eqB2lx+B14UvPoCRnA==
- dependencies:
- gaxios "^2.1.0"
- json-bigint "^0.3.0"
-
-gcp-metadata@^4.2.0:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-4.3.0.tgz#0423d06becdbfb9cbb8762eaacf14d5324997900"
- integrity sha512-L9XQUpvKJCM76YRSmcxrR4mFPzPGsgZUH+GgHMxAET8qc6+BhRJq63RLhWakgEO2KKVgeSDVfyiNjkGSADwNTA==
- dependencies:
- gaxios "^4.0.0"
- json-bigint "^1.0.0"
-
-gcs-resumable-upload@^3.3.0:
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/gcs-resumable-upload/-/gcs-resumable-upload-3.3.0.tgz#d1a866173f9b47e045d4406cafaa658dbb01e624"
- integrity sha512-MQKWi+9hOSTyg5/SI1NBW4gAjL1wlkoevHefvr1PCBBXH4uKYLsug5qRrcotWKolDPLfWS51cWaHRN0CTtQNZw==
- dependencies:
- abort-controller "^3.0.0"
- configstore "^5.0.0"
- extend "^3.0.2"
- gaxios "^4.0.0"
- google-auth-library "^7.0.0"
- pumpify "^2.0.0"
- stream-events "^1.0.4"
-
-get-caller-file@^2.0.5:
- version "2.0.5"
- resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
- integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
-
-get-intrinsic@^1.0.2:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6"
- integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==
- dependencies:
- function-bind "^1.1.1"
- has "^1.0.3"
- has-symbols "^1.0.1"
-
-get-stream@^4.1.0:
- version "4.1.0"
- 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.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3"
- integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==
- dependencies:
- pump "^3.0.0"
-
-get-stream@^6.0.0:
- version "6.0.1"
- resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7"
- integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==
-
-getpass@^0.1.1:
- version "0.1.7"
- resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
- integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=
- dependencies:
- assert-plus "^1.0.0"
-
-glob-parent@~5.1.2:
- version "5.1.2"
- 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-slash@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/glob-slash/-/glob-slash-1.0.0.tgz#fe52efa433233f74a2fe64c7abb9bc848202ab95"
- integrity sha1-/lLvpDMjP3Si/mTHq7m8hIICq5U=
-
-glob-slasher@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/glob-slasher/-/glob-slasher-1.0.1.tgz#747a0e5bb222642ee10d3e05443e109493cb0f8e"
- integrity sha1-dHoOW7IiZC7hDT4FRD4QlJPLD44=
- dependencies:
- glob-slash "^1.0.0"
- lodash.isobject "^2.4.1"
- toxic "^1.0.0"
-
-glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4:
- version "7.1.7"
- resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90"
- 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"
-
-global-dirs@^2.0.1:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-2.1.0.tgz#e9046a49c806ff04d6c1825e196c8f0091e8df4d"
- integrity sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ==
- dependencies:
- ini "1.3.7"
-
-google-auth-library@^5.0.0, google-auth-library@^5.5.0:
- version "5.10.1"
- resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-5.10.1.tgz#504ec75487ad140e68dd577c21affa363c87ddff"
- integrity sha512-rOlaok5vlpV9rSiUu5EpR0vVpc+PhN62oF4RyX/6++DG1VsaulAFEMlDYBLjJDDPI6OcNOCGAKy9UVB/3NIDXg==
- dependencies:
- arrify "^2.0.0"
- base64-js "^1.3.0"
- ecdsa-sig-formatter "^1.0.11"
- fast-text-encoding "^1.0.0"
- gaxios "^2.1.0"
- gcp-metadata "^3.4.0"
- gtoken "^4.1.0"
- jws "^4.0.0"
- lru-cache "^5.0.0"
-
-google-auth-library@^7.0.0, google-auth-library@^7.0.2, google-auth-library@^7.3.0:
- version "7.3.0"
- resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-7.3.0.tgz#946a911c72425b05f02735915f03410604466657"
- integrity sha512-MPeeMlnsYnoiiVFMwX3hgaS684aiXrSqKoDP+xL4Ejg4Z0qLvIeg4XsaChemyFI8ZUO7ApwDAzNtgmhWSDNh5w==
- dependencies:
- arrify "^2.0.0"
- base64-js "^1.3.0"
- ecdsa-sig-formatter "^1.0.11"
- fast-text-encoding "^1.0.0"
- gaxios "^4.0.0"
- gcp-metadata "^4.2.0"
- gtoken "^5.0.4"
- jws "^4.0.0"
- lru-cache "^6.0.0"
-
-google-gax@^1.14.2:
- version "1.15.4"
- resolved "https://registry.yarnpkg.com/google-gax/-/google-gax-1.15.4.tgz#dc37dea2a8c58717cd50db40f01b21cbf9da7739"
- integrity sha512-Wzl43ueWEKNsLcMJ33sPps179nD7wn6Jcl/P+ZQNS+HxdCJcoQEgJe3AmulsJnatwjBE3pVPIE4HFJNhpRGvUw==
- dependencies:
- "@grpc/grpc-js" "~1.3.6"
- "@grpc/proto-loader" "^0.5.1"
- "@types/fs-extra" "^8.0.1"
- "@types/long" "^4.0.0"
- abort-controller "^3.0.0"
- duplexify "^3.6.0"
- google-auth-library "^5.0.0"
- is-stream-ended "^0.1.4"
- lodash.at "^4.6.0"
- lodash.has "^4.5.2"
- node-fetch "^2.6.0"
- protobufjs "^6.8.9"
- retry-request "^4.0.0"
- semver "^6.0.0"
- walkdir "^0.4.0"
-
-google-gax@^2.17.1:
- version "2.19.0"
- resolved "https://registry.yarnpkg.com/google-gax/-/google-gax-2.19.0.tgz#e0e113f48688289e22053528224dfac09f019164"
- integrity sha512-2a6WY+p6YMVMmwXmkRqiLreXx67xHDZhkmflcL8aDUkl1csx9ywxEI01veoDXy6T1l0JJD6zLbl5TIbWimmXrw==
- dependencies:
- "@grpc/grpc-js" "~1.3.0"
- "@grpc/proto-loader" "^0.6.1"
- "@types/long" "^4.0.0"
- abort-controller "^3.0.0"
- duplexify "^4.0.0"
- fast-text-encoding "^1.0.3"
- google-auth-library "^7.3.0"
- is-stream-ended "^0.1.4"
- node-fetch "^2.6.1"
- object-hash "^2.1.1"
- protobufjs "^6.10.2"
- retry-request "^4.0.0"
-
-google-gax@~1.12.0:
- version "1.12.0"
- resolved "https://registry.yarnpkg.com/google-gax/-/google-gax-1.12.0.tgz#f926f7e6abda245db38ecbebbbf58daaf3a8f687"
- integrity sha512-BeeoxVO6y9K20gUsexUwptutd0PfrTItrA02JWwwstlBIOAcvgFp86MHWufQsnrkPVhxBjHXq65aIkSejtJjDg==
- dependencies:
- "@grpc/grpc-js" "^0.6.12"
- "@grpc/proto-loader" "^0.5.1"
- "@types/long" "^4.0.0"
- abort-controller "^3.0.0"
- duplexify "^3.6.0"
- google-auth-library "^5.0.0"
- is-stream-ended "^0.1.4"
- lodash.at "^4.6.0"
- lodash.has "^4.5.2"
- node-fetch "^2.6.0"
- protobufjs "^6.8.8"
- retry-request "^4.0.0"
- semver "^6.0.0"
- walkdir "^0.4.0"
-
-google-p12-pem@^2.0.0:
- version "2.0.5"
- resolved "https://registry.yarnpkg.com/google-p12-pem/-/google-p12-pem-2.0.5.tgz#b1c44164d567ae894f7a19b4ff362a06be5b793b"
- integrity sha512-7RLkxwSsMsYh9wQ5Vb2zRtkAHvqPvfoMGag+nugl1noYO7gf0844Yr9TIFA5NEBMAeVt2Z+Imu7CQMp3oNatzQ==
- dependencies:
- node-forge "^0.10.0"
-
-google-p12-pem@^3.0.3:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/google-p12-pem/-/google-p12-pem-3.1.1.tgz#98fb717b722d12196a3e5b550c44517562269859"
- integrity sha512-e9CwdD2QYkpvJsktki3Bm8P8FSGIneF+/42a9F9QHcQvJ73C2RoYZdrwRl6BhwksWtzl65gT4OnBROhUIFw95Q==
- dependencies:
- node-forge "^0.10.0"
-
-got@^9.6.0:
- version "9.6.0"
- 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"
- "@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@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.6:
- version "4.2.6"
- resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee"
- integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==
-
-gtoken@^4.1.0:
- version "4.1.4"
- resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-4.1.4.tgz#925ff1e7df3aaada06611d30ea2d2abf60fcd6a7"
- integrity sha512-VxirzD0SWoFUo5p8RDP8Jt2AGyOmyYcT/pOUgDKJCK+iSw0TMqwrVfY37RXTNmoKwrzmDHSk0GMT9FsgVmnVSA==
- dependencies:
- gaxios "^2.1.0"
- google-p12-pem "^2.0.0"
- jws "^4.0.0"
- mime "^2.2.0"
-
-gtoken@^5.0.4:
- version "5.3.0"
- resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-5.3.0.tgz#6536eb2880d9829f0b9d78f756795d4d9064b217"
- integrity sha512-mCcISYiaRZrJpfqOs0QWa6lfEM/C1V9ASkzFmuz43XBb5s1Vynh+CZy1ECeeJXVGx2PRByjYzb4Y4/zr1byr0w==
- dependencies:
- gaxios "^4.0.0"
- google-p12-pem "^3.0.3"
- jws "^4.0.0"
-
-har-schema@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
- integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
-
-har-validator@~5.1.3:
- version "5.1.5"
- resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd"
- integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==
- dependencies:
- ajv "^6.12.3"
- har-schema "^2.0.0"
-
-has-ansi@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
- integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=
- dependencies:
- ansi-regex "^2.0.0"
-
-has-flag@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51"
- integrity sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=
-
-has-flag@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
- integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
-
-has-flag@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
- integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
-
-has-symbols@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423"
- integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==
-
-has-unicode@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
- integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=
-
-has-yarn@^2.1.0:
- version "2.1.0"
- 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.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
- integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
- dependencies:
- function-bind "^1.1.1"
-
-hash-stream-validation@^0.2.2:
- version "0.2.4"
- resolved "https://registry.yarnpkg.com/hash-stream-validation/-/hash-stream-validation-0.2.4.tgz#ee68b41bf822f7f44db1142ec28ba9ee7ccb7512"
- integrity sha512-Gjzu0Xn7IagXVkSu9cSFuK1fqzwtLwFhNhVL8IFJijRNMgUttFbBSIAzKuSIrsFMO1+g1RlsoN49zPIbwPDMGQ==
-
-home-dir@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/home-dir/-/home-dir-1.0.0.tgz#2917eb44bdc9072ceda942579543847e3017fe4e"
- integrity sha1-KRfrRL3JByztqUJXlUOEfjAX/k4=
-
-http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0:
- version "4.1.0"
- 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.2:
- version "1.7.2"
- resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f"
- integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==
- dependencies:
- depd "~1.1.2"
- inherits "2.0.3"
- setprototypeof "1.1.1"
- statuses ">= 1.5.0 < 2"
- toidentifier "1.0.0"
-
-http-errors@1.7.3, http-errors@~1.7.2:
- version "1.7.3"
- resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06"
- 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"
-
-http-parser-js@>=0.5.1:
- version "0.5.3"
- resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.3.tgz#01d2709c79d41698bb01d4decc5e9da4e4a033d9"
- integrity sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==
-
-http-proxy-agent@^4.0.0, http-proxy-agent@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a"
- integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==
- dependencies:
- "@tootallnate/once" "1"
- agent-base "6"
- debug "4"
-
-http-signature@~1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
- integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=
- dependencies:
- assert-plus "^1.0.0"
- jsprim "^1.2.2"
- sshpk "^1.7.0"
-
-https-proxy-agent@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2"
- integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==
- dependencies:
- agent-base "6"
- debug "4"
-
-human-signals@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3"
- integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==
-
-humanize-ms@^1.2.1:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed"
- integrity sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=
- dependencies:
- ms "^2.0.0"
-
-husky@^4.2.5:
- version "4.3.8"
- resolved "https://registry.yarnpkg.com/husky/-/husky-4.3.8.tgz#31144060be963fd6850e5cc8f019a1dfe194296d"
- integrity sha512-LCqqsB0PzJQ/AlCgfrfzRe3e3+NvmefAdKQhRYpxS4u6clblBoDdzzvHi8fmxKRzvMxPY/1WZWzomPZww0Anow==
- dependencies:
- chalk "^4.0.0"
- ci-info "^2.0.0"
- compare-versions "^3.6.0"
- cosmiconfig "^7.0.0"
- find-versions "^4.0.0"
- opencollective-postinstall "^2.0.2"
- pkg-dir "^5.0.0"
- please-upgrade-node "^3.2.0"
- slash "^3.0.0"
- which-pm-runs "^1.0.0"
-
-iconv-lite@0.4.24, iconv-lite@^0.4.24:
- version "0.4.24"
- resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
- integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
- dependencies:
- safer-buffer ">= 2.1.2 < 3"
-
-iconv-lite@^0.6.2:
- version "0.6.3"
- resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
- integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==
- dependencies:
- safer-buffer ">= 2.1.2 < 3.0.0"
-
-ieee754@^1.1.13:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
- integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
-
-ignore@^5.1.4:
- version "5.1.8"
- resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57"
- integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==
-
-import-fresh@^3.2.1:
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
- integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
- dependencies:
- parent-module "^1.0.0"
- resolve-from "^4.0.0"
-
-import-lazy@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43"
- integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=
-
-imurmurhash@^0.1.4:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
- integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
-
-indent-string@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
- integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
-
-infer-owner@^1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467"
- integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==
-
-inflight@^1.0.4:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
- integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
- dependencies:
- once "^1.3.0"
- wrappy "1"
-
-inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
- integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
-
-inherits@2.0.3:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
- integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
-
-ini@1.3.7:
- version "1.3.7"
- 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.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
- integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
-
-inquirer@~6.3.1:
- version "6.3.1"
- resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.3.1.tgz#7a413b5e7950811013a3db491c61d1f3b776e8e7"
- integrity sha512-MmL624rfkFt4TG9y/Jvmt8vdmOo836U7Y0Hxr2aFk3RelZEGX4Igk0KabWrcaaZaTv9uzglOqWh1Vly+FAWAXA==
- dependencies:
- ansi-escapes "^3.2.0"
- chalk "^2.4.2"
- cli-cursor "^2.1.0"
- cli-width "^2.0.0"
- external-editor "^3.0.3"
- figures "^2.0.0"
- lodash "^4.17.11"
- mute-stream "0.0.7"
- run-async "^2.2.0"
- rxjs "^6.4.0"
- string-width "^2.1.0"
- strip-ansi "^5.1.0"
- through "^2.3.6"
-
-install-artifact-from-github@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/install-artifact-from-github/-/install-artifact-from-github-1.2.0.tgz#adcbd123c16a4337ec44ea76d0ebf253cc16b074"
- integrity sha512-3OxCPcY55XlVM3kkfIpeCgmoSKnMsz2A3Dbhsq0RXpIknKQmrX1YiznCeW9cD2ItFmDxziA3w6Eg8d80AoL3oA==
-
-ip-regex@^4.1.0:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-4.3.0.tgz#687275ab0f57fa76978ff8f4dddc8a23d5990db5"
- integrity sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==
-
-ip@^1.1.5:
- version "1.1.5"
- resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
- integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=
-
-ipaddr.js@1.9.1:
- version "1.9.1"
- resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
- integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==
-
-is-arrayish@^0.2.1:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
- integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=
-
-is-arrayish@^0.3.1:
- version "0.3.2"
- resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03"
- integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==
-
-is-binary-path@~2.1.0:
- version "2.1.0"
- 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-ci@^2.0.0:
- version "2.0.0"
- 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.5.0"
- resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.5.0.tgz#f754843617c70bfd29b7bd87327400cda5c18491"
- integrity sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg==
- dependencies:
- has "^1.0.3"
-
-is-extglob@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
- integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
-
-is-fullwidth-code-point@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
- integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs=
- dependencies:
- number-is-nan "^1.0.0"
-
-is-fullwidth-code-point@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
- integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=
-
-is-fullwidth-code-point@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
- integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
-
-is-glob@^4.0.1, is-glob@~4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc"
- integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==
- dependencies:
- is-extglob "^2.1.1"
-
-is-installed-globally@^0.3.1:
- version "0.3.2"
- 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"
- is-path-inside "^3.0.1"
-
-is-lambda@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5"
- integrity sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU=
-
-is-npm@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-4.0.0.tgz#c90dd8380696df87a7a6d823c20d0b12bbe3c84d"
- integrity sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==
-
-is-number@^7.0.0:
- version "7.0.0"
- 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.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.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283"
- integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==
-
-is-promise@^2.2.2:
- version "2.2.2"
- resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1"
- integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==
-
-is-stream-ended@^0.1.4:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/is-stream-ended/-/is-stream-ended-0.1.4.tgz#f50224e95e06bce0e356d440a4827cd35b267eda"
- integrity sha512-xj0XPvmr7bQFTvirqnFr50o0hQIh6ZItDqloxt5aJrR4NQsYeSsyFQERYGCAzfindAcnKjINnwEEgLx4IqVzQw==
-
-is-stream@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
- integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==
-
-is-typedarray@^1.0.0, is-typedarray@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
- integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
-
-is-url@^1.2.2, is-url@^1.2.4:
- version "1.2.4"
- resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52"
- integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==
-
-is-wsl@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d"
- integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=
-
-is-yarn-global@^0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232"
- integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==
-
-is2@^2.0.6:
- version "2.0.7"
- resolved "https://registry.yarnpkg.com/is2/-/is2-2.0.7.tgz#d084e10cab3bd45d6c9dfde7a48599fcbb93fcac"
- integrity sha512-4vBQoURAXC6hnLFxD4VW7uc04XiwTTl/8ydYJxKvPwkWQrSjInkuM5VZVg6BGr1/natq69zDuvO9lGpLClJqvA==
- dependencies:
- deep-is "^0.1.3"
- ip-regex "^4.1.0"
- is-url "^1.2.4"
-
-isarray@0.0.1:
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
- integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=
-
-isarray@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
- integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
-
-isexe@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
- integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
-
-isstream@~0.1.2:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
- integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
-
-jju@^1.1.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/jju/-/jju-1.4.0.tgz#a3abe2718af241a2b2904f84a625970f389ae32a"
- integrity sha1-o6vicYryQaKykE+EpiWXDzia4yo=
-
-join-path@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/join-path/-/join-path-1.1.1.tgz#10535a126d24cbd65f7ffcdf15ef2e631076b505"
- integrity sha1-EFNaEm0ky9Zff/zfFe8uYxB2tQU=
- dependencies:
- as-array "^2.0.0"
- url-join "0.0.1"
- valid-url "^1"
-
-jose@^2.0.5:
- version "2.0.5"
- resolved "https://registry.yarnpkg.com/jose/-/jose-2.0.5.tgz#29746a18d9fff7dcf9d5d2a6f62cb0c7cd27abd3"
- integrity sha512-BAiDNeDKTMgk4tvD0BbxJ8xHEHBZgpeRZ1zGPPsitSyMgjoMWiLGYAE7H7NpP5h0lPppQajQs871E8NHUrzVPA==
- dependencies:
- "@panva/asn1.js" "^1.0.0"
-
-js-tokens@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
- integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
-
-js-yaml@^3.13.1:
- version "3.14.1"
- resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537"
- integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==
- dependencies:
- argparse "^1.0.7"
- esprima "^4.0.0"
-
-js-yaml@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
- integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
- dependencies:
- argparse "^2.0.1"
-
-jsbn@~0.1.0:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
- integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
-
-json-bigint@^0.3.0:
- version "0.3.1"
- resolved "https://registry.yarnpkg.com/json-bigint/-/json-bigint-0.3.1.tgz#0c1729d679f580d550899d6a2226c228564afe60"
- integrity sha512-DGWnSzmusIreWlEupsUelHrhwmPPE+FiQvg+drKfk2p+bdEYa5mp4PJ8JsCWqae0M2jQNb0HPvnwvf1qOTThzQ==
- dependencies:
- bignumber.js "^9.0.0"
-
-json-bigint@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/json-bigint/-/json-bigint-1.0.0.tgz#ae547823ac0cad8398667f8cd9ef4730f5b01ff1"
- integrity sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==
- dependencies:
- bignumber.js "^9.0.0"
-
-json-buffer@3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898"
- integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=
-
-json-parse-even-better-errors@^2.3.0:
- version "2.3.1"
- 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-parse-helpfulerror@^1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/json-parse-helpfulerror/-/json-parse-helpfulerror-1.0.3.tgz#13f14ce02eed4e981297b64eb9e3b932e2dd13dc"
- integrity sha1-E/FM4C7tTpgSl7ZOueO5MuLdE9w=
- dependencies:
- jju "^1.1.0"
-
-json-ptr@^2.2.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/json-ptr/-/json-ptr-2.2.0.tgz#a4de4ed638cb23ae4cd4b51f8bf972a1c2293f1e"
- integrity sha512-w9f6/zhz4kykltXMG7MLJWMajxiPj0q+uzQPR1cggNAE/sXoq/C5vjUb/7QNcC3rJsVIIKy37ALTXy1O+3c8QQ==
- dependencies:
- tslib "^2.2.0"
-
-json-schema-traverse@^0.4.1:
- version "0.4.1"
- resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
- integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
-
-json-schema-traverse@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2"
- integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==
-
-json-schema@0.2.3:
- version "0.2.3"
- resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
- integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
-
-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 sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
-
-jsonfile@^2.1.0:
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8"
- integrity sha1-NzaitCi4e72gzIO1P6PWM6NcKug=
- optionalDependencies:
- graceful-fs "^4.1.6"
-
-jsonfile@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
- integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=
- optionalDependencies:
- graceful-fs "^4.1.6"
-
-jsonparse@^1.2.0:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
- integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=
-
-jsonschema@^1.0.2:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.4.0.tgz#1afa34c4bc22190d8e42271ec17ac8b3404f87b2"
- integrity sha512-/YgW6pRMr6M7C+4o8kS+B/2myEpHCrxO4PEWnqJNBFMjn7EWXqlQ4tGwL6xTHeRplwuZmcAncdvfOad1nT2yMw==
-
-jsonwebtoken@^8.2.1, jsonwebtoken@^8.5.1:
- version "8.5.1"
- resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d"
- 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"
-
-jsprim@^1.2.2:
- version "1.4.1"
- resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
- integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=
- dependencies:
- assert-plus "1.0.0"
- extsprintf "1.3.0"
- json-schema "0.2.3"
- verror "1.10.0"
-
-jwa@^1.4.1:
- version "1.4.1"
- 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"
- ecdsa-sig-formatter "1.0.11"
- safe-buffer "^5.0.1"
-
-jwa@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/jwa/-/jwa-2.0.0.tgz#a7e9c3f29dae94027ebcaf49975c9345593410fc"
- integrity sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==
- dependencies:
- buffer-equal-constant-time "1.0.1"
- ecdsa-sig-formatter "1.0.11"
- safe-buffer "^5.0.1"
-
-jwks-rsa@^2.0.2:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/jwks-rsa/-/jwks-rsa-2.0.4.tgz#59d95e39f300783a8582ef8aa37d5ebbc6a8aa6f"
- integrity sha512-iJqVCECYZZ+3oPmY1qXv3Fq+3ywDtuNEVBvG41pPlaR0zyGxa12nC0beAOBBUhETJmc05puS50mRQN4NkCGhmg==
- dependencies:
- "@types/express-jwt" "0.0.42"
- debug "^4.3.2"
- jose "^2.0.5"
- limiter "^1.1.5"
- lru-memoizer "^2.1.4"
-
-jws@^3.2.2:
- version "3.2.2"
- resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304"
- integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==
- dependencies:
- jwa "^1.4.1"
- safe-buffer "^5.0.1"
-
-jws@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/jws/-/jws-4.0.0.tgz#2d4e8cf6a318ffaa12615e9dec7e86e6c97310f4"
- integrity sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==
- dependencies:
- jwa "^2.0.0"
- safe-buffer "^5.0.1"
-
-keyv@^3.0.0:
- version "3.1.0"
- 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"
-
-kuler@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3"
- integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==
-
-latest-version@^5.0.0:
- version "5.1.0"
- 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"
-
-lazystream@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4"
- integrity sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=
- dependencies:
- readable-stream "^2.0.5"
-
-leven@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2"
- integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==
-
-limiter@^1.1.5:
- version "1.1.5"
- resolved "https://registry.yarnpkg.com/limiter/-/limiter-1.1.5.tgz#8f92a25b3b16c6131293a0cc834b4a838a2aa7c2"
- integrity sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==
-
-lines-and-columns@^1.1.6:
- version "1.1.6"
- resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00"
- integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=
-
-listenercount@~1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/listenercount/-/listenercount-1.0.1.tgz#84c8a72ab59c4725321480c975e6508342e70937"
- integrity sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=
-
-locate-path@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
- integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==
- dependencies:
- p-locate "^4.1.0"
-
-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._isnative@~2.4.1:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/lodash._isnative/-/lodash._isnative-2.4.1.tgz#3ea6404b784a7be836c7b57580e1cdf79b14832c"
- integrity sha1-PqZAS3hKe+g2x7V1gOHN95sUgyw=
-
-lodash._objecttypes@~2.4.1:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz#7c0b7f69d98a1f76529f890b0cdb1b4dfec11c11"
- integrity sha1-fAt/admKH3ZSn4kLDNsbTf7BHBE=
-
-lodash._shimkeys@~2.4.1:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz#6e9cc9666ff081f0b5a6c978b83e242e6949d203"
- integrity sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=
- dependencies:
- lodash._objecttypes "~2.4.1"
-
-lodash.at@^4.6.0:
- version "4.6.0"
- resolved "https://registry.yarnpkg.com/lodash.at/-/lodash.at-4.6.0.tgz#93cdce664f0a1994ea33dd7cd40e23afd11b0ff8"
- integrity sha1-k83OZk8KGZTqM9181A4jr9EbD/g=
-
-lodash.camelcase@^4.3.0:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
- integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY=
-
-lodash.clonedeep@^4.5.0:
- version "4.5.0"
- resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
- integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=
-
-lodash.defaults@^4.2.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
- integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=
-
-lodash.difference@^4.5.0:
- version "4.5.0"
- resolved "https://registry.yarnpkg.com/lodash.difference/-/lodash.difference-4.5.0.tgz#9ccb4e505d486b91651345772885a2df27fd017c"
- integrity sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=
-
-lodash.flatten@^4.4.0:
- version "4.4.0"
- resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f"
- integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=
-
-lodash.has@^4.5.2:
- version "4.5.2"
- resolved "https://registry.yarnpkg.com/lodash.has/-/lodash.has-4.5.2.tgz#d19f4dc1095058cccbe2b0cdf4ee0fe4aa37c862"
- integrity sha1-0Z9NwQlQWMzL4rDN9O4P5Ko3yGI=
-
-lodash.includes@^4.3.0:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f"
- integrity sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=
-
-lodash.isarguments@2.4.x:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-2.4.1.tgz#4931a9c08253adf091ae7ca192258a973876ecca"
- integrity sha1-STGpwIJTrfCRrnyhkiWKlzh27Mo=
-
-lodash.isarguments@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a"
- integrity sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=
-
-lodash.isboolean@^3.0.3:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6"
- integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=
-
-lodash.isinteger@^4.0.4:
- version "4.0.4"
- resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343"
- integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=
-
-lodash.isnumber@^3.0.3:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc"
- integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=
-
-lodash.isobject@^2.4.1, lodash.isobject@~2.4.1:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/lodash.isobject/-/lodash.isobject-2.4.1.tgz#5a2e47fe69953f1ee631a7eba1fe64d2d06558f5"
- integrity sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=
- dependencies:
- lodash._objecttypes "~2.4.1"
-
-lodash.isobject@^3.0.0:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/lodash.isobject/-/lodash.isobject-3.0.2.tgz#3c8fb8d5b5bf4bf90ae06e14f2a530a4ed935e1d"
- integrity sha1-PI+41bW/S/kK4G4U8qUwpO2TXh0=
-
-lodash.isplainobject@^4.0.6:
- version "4.0.6"
- resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
- integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=
-
-lodash.isstring@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451"
- integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=
-
-lodash.keys@~2.4.1:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-2.4.1.tgz#48dea46df8ff7632b10d706b8acb26591e2b3727"
- integrity sha1-SN6kbfj/djKxDXBrissmWR4rNyc=
- dependencies:
- lodash._isnative "~2.4.1"
- lodash._shimkeys "~2.4.1"
- lodash.isobject "~2.4.1"
-
-lodash.once@^4.0.0:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
- integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=
-
-lodash.snakecase@^4.1.1:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz#39d714a35357147837aefd64b5dcbb16becd8f8d"
- integrity sha1-OdcUo1NXFHg3rv1ktdy7Fr7Nj40=
-
-lodash.toarray@^4.4.0:
- version "4.4.0"
- resolved "https://registry.yarnpkg.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz#24c4bfcd6b2fba38bfd0594db1179d8e9b656561"
- integrity sha1-JMS/zWsvuji/0FlNsRedjptlZWE=
-
-lodash.union@^4.6.0:
- version "4.6.0"
- resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88"
- integrity sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=
-
-lodash.values@^2.4.1:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/lodash.values/-/lodash.values-2.4.1.tgz#abf514436b3cb705001627978cbcf30b1280eea4"
- integrity sha1-q/UUQ2s8twUAFieXjLzzCxKA7qQ=
- dependencies:
- lodash.keys "~2.4.1"
-
-lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.19, lodash@^4.17.21, lodash@^4.17.5:
- version "4.17.21"
- resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
- integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
-
-log-symbols@^2.2.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a"
- integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==
- dependencies:
- chalk "^2.0.1"
-
-logform@^2.2.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/logform/-/logform-2.2.0.tgz#40f036d19161fc76b68ab50fdc7fe495544492f2"
- integrity sha512-N0qPlqfypFx7UHNn4B3lzS/b0uLqt2hmuoa+PpuXNYgozdJYAyauF5Ky0BWVjrxDlMWiT3qN4zPq3vVAfZy7Yg==
- dependencies:
- colors "^1.2.1"
- fast-safe-stringify "^2.0.4"
- fecha "^4.2.0"
- ms "^2.1.1"
- triple-beam "^1.3.0"
-
-long@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28"
- integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==
-
-lowercase-keys@^1.0.0, lowercase-keys@^1.0.1:
- version "1.0.1"
- 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.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479"
- integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==
-
-lru-cache@^5.0.0:
- version "5.1.1"
- resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
- integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==
- dependencies:
- yallist "^3.0.2"
-
-lru-cache@^6.0.0:
- version "6.0.0"
- resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
- integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
- dependencies:
- yallist "^4.0.0"
-
-lru-cache@~4.0.0:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.0.2.tgz#1d17679c069cda5d040991a09dbc2c0db377e55e"
- integrity sha1-HRdnnAac2l0ECZGgnbwsDbN35V4=
- dependencies:
- pseudomap "^1.0.1"
- yallist "^2.0.0"
-
-lru-memoizer@^2.1.4:
- version "2.1.4"
- resolved "https://registry.yarnpkg.com/lru-memoizer/-/lru-memoizer-2.1.4.tgz#b864d92b557f00b1eeb322156a0409cb06dafac6"
- integrity sha512-IXAq50s4qwrOBrXJklY+KhgZF+5y98PDaNo0gi/v2KQBFLyWr+JyFvijZXkGKjQj/h9c0OwoE+JZbwUXce76hQ==
- dependencies:
- lodash.clonedeep "^4.5.0"
- lru-cache "~4.0.0"
-
-lru-queue@^0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3"
- integrity sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=
- dependencies:
- es5-ext "~0.10.2"
-
-make-dir@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f"
- integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==
- dependencies:
- semver "^6.0.0"
-
-make-error@^1.1.1:
- version "1.3.6"
- resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
- integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
-
-make-fetch-happen@^8.0.14:
- version "8.0.14"
- resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-8.0.14.tgz#aaba73ae0ab5586ad8eaa68bd83332669393e222"
- integrity sha512-EsS89h6l4vbfJEtBZnENTOFk8mCRpY5ru36Xe5bcX1KYIli2mkSHqoFsp5O1wMDvTJJzxe/4THpCTtygjeeGWQ==
- dependencies:
- agentkeepalive "^4.1.3"
- cacache "^15.0.5"
- http-cache-semantics "^4.1.0"
- http-proxy-agent "^4.0.1"
- https-proxy-agent "^5.0.0"
- is-lambda "^1.0.1"
- lru-cache "^6.0.0"
- minipass "^3.1.3"
- minipass-collect "^1.0.2"
- minipass-fetch "^1.3.2"
- minipass-flush "^1.0.5"
- minipass-pipeline "^1.2.4"
- promise-retry "^2.0.1"
- socks-proxy-agent "^5.0.0"
- ssri "^8.0.0"
-
-marked-terminal@^3.3.0:
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/marked-terminal/-/marked-terminal-3.3.0.tgz#25ce0c0299285998c7636beaefc87055341ba1bd"
- integrity sha512-+IUQJ5VlZoAFsM5MHNT7g3RHSkA3eETqhRCdXv4niUMAKHQ7lb1yvAcuGPmm4soxhmtX13u4Li6ZToXtvSEH+A==
- dependencies:
- ansi-escapes "^3.1.0"
- cardinal "^2.1.1"
- chalk "^2.4.1"
- cli-table "^0.3.1"
- node-emoji "^1.4.1"
- supports-hyperlinks "^1.0.1"
-
-marked@^0.7.0:
- version "0.7.0"
- resolved "https://registry.yarnpkg.com/marked/-/marked-0.7.0.tgz#b64201f051d271b1edc10a04d1ae9b74bb8e5c0e"
- integrity sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg==
-
-media-typer@0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
- integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
-
-memoizee@^0.4.14:
- version "0.4.15"
- resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.15.tgz#e6f3d2da863f318d02225391829a6c5956555b72"
- integrity sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==
- dependencies:
- d "^1.0.1"
- es5-ext "^0.10.53"
- es6-weak-map "^2.0.3"
- event-emitter "^0.3.5"
- is-promise "^2.2.2"
- lru-queue "^0.1.0"
- next-tick "^1.1.0"
- timers-ext "^0.1.7"
-
-merge-descriptors@1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
- integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=
-
-merge-stream@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
- integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
-
-methods@~1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
- integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
-
-mime-db@1.48.0:
- version "1.48.0"
- resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.48.0.tgz#e35b31045dd7eada3aaad537ed88a33afbef2d1d"
- integrity sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==
-
-"mime-db@>= 1.43.0 < 2":
- version "1.49.0"
- resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.49.0.tgz#f3dfde60c99e9cf3bc9701d687778f537001cbed"
- integrity sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA==
-
-mime-types@^2.0.8, mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.19, mime-types@~2.1.24:
- version "2.1.31"
- resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.31.tgz#a00d76b74317c61f9c2db2218b8e9f8e9c5c9e6b"
- integrity sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==
- dependencies:
- mime-db "1.48.0"
-
-mime@1.6.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
- integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
-
-mime@^2.2.0:
- version "2.5.2"
- resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe"
- integrity sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==
-
-mimic-fn@^1.0.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
- integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==
-
-mimic-fn@^2.1.0:
- version "2.1.0"
- 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.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b"
- integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==
-
-minimatch@^3.0.4:
- version "3.0.4"
- resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
- integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
- dependencies:
- brace-expansion "^1.1.7"
-
-minimist@^1.1.0, minimist@^1.2.0, minimist@^1.2.5:
- version "1.2.5"
- resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
- integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
-
-minipass-collect@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617"
- integrity sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==
- dependencies:
- minipass "^3.0.0"
-
-minipass-fetch@^1.3.2:
- version "1.3.4"
- resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-1.3.4.tgz#63f5af868a38746ca7b33b03393ddf8c291244fe"
- integrity sha512-TielGogIzbUEtd1LsjZFs47RWuHHfhl6TiCx1InVxApBAmQ8bL0dL5ilkLGcRvuyW/A9nE+Lvn855Ewz8S0PnQ==
- dependencies:
- minipass "^3.1.0"
- minipass-sized "^1.0.3"
- minizlib "^2.0.0"
- optionalDependencies:
- encoding "^0.1.12"
-
-minipass-flush@^1.0.5:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373"
- integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==
- dependencies:
- minipass "^3.0.0"
-
-minipass-pipeline@^1.2.2, minipass-pipeline@^1.2.4:
- version "1.2.4"
- resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c"
- integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==
- dependencies:
- minipass "^3.0.0"
-
-minipass-sized@^1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/minipass-sized/-/minipass-sized-1.0.3.tgz#70ee5a7c5052070afacfbc22977ea79def353b70"
- integrity sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==
- dependencies:
- minipass "^3.0.0"
-
-minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0:
- version "2.9.0"
- resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6"
- integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==
- dependencies:
- safe-buffer "^5.1.2"
- yallist "^3.0.0"
-
-minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3:
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.3.tgz#7d42ff1f39635482e15f9cdb53184deebd5815fd"
- integrity sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==
- dependencies:
- yallist "^4.0.0"
-
-minizlib@^1.2.1:
- version "1.3.3"
- resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d"
- integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==
- dependencies:
- minipass "^2.9.0"
-
-minizlib@^2.0.0, minizlib@^2.1.1:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
- integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==
- dependencies:
- minipass "^3.0.0"
- yallist "^4.0.0"
-
-"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.3, mkdirp@^0.5.5:
- version "0.5.5"
- resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
- integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
- dependencies:
- minimist "^1.2.5"
-
-mkdirp@^1.0.3, mkdirp@^1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
- integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
-
-morgan@^1.10.0, morgan@^1.8.2:
- version "1.10.0"
- resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.10.0.tgz#091778abc1fc47cd3509824653dae1faab6b17d7"
- integrity sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==
- dependencies:
- basic-auth "~2.0.1"
- debug "2.6.9"
- depd "~2.0.0"
- on-finished "~2.3.0"
- on-headers "~1.0.2"
-
-mri@^1.1.5:
- version "1.1.6"
- resolved "https://registry.yarnpkg.com/mri/-/mri-1.1.6.tgz#49952e1044db21dbf90f6cd92bc9c9a777d415a6"
- integrity sha512-oi1b3MfbyGa7FJMP9GmLTttni5JoICpYBRlq+x5V16fZbLsnL9N3wFqqIm/nIG43FjUFkFh9Epzp/kzUGUnJxQ==
-
-ms@2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
- integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
-
-ms@2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
- integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
-
-ms@2.1.2:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
- integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
-
-ms@^2.0.0, ms@^2.1.1:
- version "2.1.3"
- resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
- integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
-
-multimatch@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-4.0.0.tgz#8c3c0f6e3e8449ada0af3dd29efb491a375191b3"
- integrity sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==
- dependencies:
- "@types/minimatch" "^3.0.3"
- array-differ "^3.0.0"
- array-union "^2.1.0"
- arrify "^2.0.1"
- minimatch "^3.0.4"
-
-mute-stream@0.0.7:
- version "0.0.7"
- resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
- integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=
-
-nan@^2.14.2:
- version "2.14.2"
- resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19"
- integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==
-
-nash@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/nash/-/nash-3.0.0.tgz#bced3a0cb8434c2ad30d1a0d567cfc0c37128eea"
- integrity sha512-M5SahEycXUmko3zOvsBkF6p94CWLhnyy9hfpQ9Qzp+rQkQ8D1OaTlfTl1OBWktq9Fak3oDXKU+ev7tiMaMu+1w==
- dependencies:
- async "^1.3.0"
- flat-arguments "^1.0.0"
- lodash "^4.17.5"
- minimist "^1.1.0"
-
-negotiator@0.6.2:
- version "0.6.2"
- resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
- integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
-
-next-tick@1, next-tick@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb"
- integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==
-
-next-tick@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c"
- integrity sha1-yobR/ogoFpsBICCOPchCS524NCw=
-
-nice-try@^1.0.4:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
- integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
-
-node-emoji@^1.4.1:
- version "1.10.0"
- resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.10.0.tgz#8886abd25d9c7bb61802a658523d1f8d2a89b2da"
- integrity sha512-Yt3384If5H6BYGVHiHwTL+99OzJKHhgp82S8/dktEK73T26BazdgZ4JZh92xSVtGNJvz9UbXdNAc5hcrXV42vw==
- dependencies:
- lodash.toarray "^4.4.0"
-
-node-fetch@^2.3.0, node-fetch@^2.6.0, node-fetch@^2.6.1:
- version "2.6.1"
- resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
- integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
-
-node-forge@^0.10.0:
- version "0.10.0"
- resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3"
- integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==
-
-node-gyp@^8.0.0:
- version "8.1.0"
- resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-8.1.0.tgz#81f43283e922d285c886fb0e0f520a7fd431d8c2"
- integrity sha512-o2elh1qt7YUp3lkMwY3/l4KF3j/A3fI/Qt4NH+CQQgPJdqGE9y7qnP84cjIWN27Q0jJkrSAhCVDg+wBVNBYdBg==
- dependencies:
- env-paths "^2.2.0"
- glob "^7.1.4"
- graceful-fs "^4.2.6"
- make-fetch-happen "^8.0.14"
- nopt "^5.0.0"
- npmlog "^4.1.2"
- rimraf "^3.0.2"
- semver "^7.3.5"
- tar "^6.1.0"
- which "^2.0.2"
-
-nopt@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88"
- integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==
- dependencies:
- abbrev "1"
-
-normalize-path@^3.0.0, normalize-path@~3.0.0:
- version "3.0.0"
- 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.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a"
- integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==
-
-npm-run-path@^4.0.0:
- version "4.0.1"
- 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.1.2:
- version "4.1.2"
- resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
- 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"
-
-number-is-nan@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
- integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
-
-oauth-sign@~0.9.0:
- version "0.9.0"
- resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
- integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
-
-object-assign@^4, object-assign@^4.1.0:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
- integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
-
-object-hash@^2.1.1:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5"
- integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==
-
-object-inspect@^1.9.0:
- version "1.11.0"
- resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1"
- integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==
-
-on-finished@^2.2.0, on-finished@~2.3.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
- integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=
- dependencies:
- ee-first "1.1.1"
-
-on-headers@^1.0.0, on-headers@~1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f"
- integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==
-
-once@^1.3.0, once@^1.3.1, once@^1.4.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
- integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
- dependencies:
- wrappy "1"
-
-one-time@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/one-time/-/one-time-1.0.0.tgz#e06bc174aed214ed58edede573b433bbf827cb45"
- integrity sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==
- dependencies:
- fn.name "1.x.x"
-
-onetime@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4"
- integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=
- dependencies:
- mimic-fn "^1.0.0"
-
-onetime@^5.1.0:
- version "5.1.2"
- resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
- integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
- dependencies:
- mimic-fn "^2.1.0"
-
-open@^6.3.0:
- version "6.4.0"
- resolved "https://registry.yarnpkg.com/open/-/open-6.4.0.tgz#5c13e96d0dc894686164f18965ecfe889ecfc8a9"
- integrity sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg==
- dependencies:
- is-wsl "^1.1.0"
-
-openapi3-ts@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/openapi3-ts/-/openapi3-ts-2.0.1.tgz#b270aecea09e924f1886bc02a72608fca5a98d85"
- integrity sha512-v6X3iwddhi276siej96jHGIqTx3wzVfMTmpGJEQDt7GPI7pI6sywItURLzpEci21SBRpPN/aOWSF5mVfFVNmcg==
- dependencies:
- yaml "^1.10.0"
-
-opencollective-postinstall@^2.0.2:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz#7a0fff978f6dbfa4d006238fbac98ed4198c3259"
- integrity sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==
-
-ora@^3.4.0:
- version "3.4.0"
- resolved "https://registry.yarnpkg.com/ora/-/ora-3.4.0.tgz#bf0752491059a3ef3ed4c85097531de9fdbcd318"
- integrity sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg==
- dependencies:
- chalk "^2.4.2"
- cli-cursor "^2.1.0"
- cli-spinners "^2.0.0"
- log-symbols "^2.2.0"
- strip-ansi "^5.2.0"
- wcwidth "^1.0.1"
-
-os-tmpdir@~1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
- integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
-
-p-cancelable@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc"
- integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==
-
-p-defer@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-3.0.0.tgz#d1dceb4ee9b2b604b1d94ffec83760175d4e6f83"
- integrity sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw==
-
-p-limit@^2.2.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
- integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==
- dependencies:
- p-try "^2.0.0"
-
-p-limit@^3.0.1, p-limit@^3.0.2:
- 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.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@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b"
- integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==
- dependencies:
- aggregate-error "^3.0.0"
-
-p-try@^2.0.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
- integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
-
-package-json@^6.3.0:
- version "6.5.0"
- resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0"
- integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==
- dependencies:
- got "^9.6.0"
- registry-auth-token "^4.0.0"
- registry-url "^5.0.0"
- semver "^6.2.0"
-
-parent-module@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
- integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==
- dependencies:
- callsites "^3.0.0"
-
-parse-json@^5.0.0:
- version "5.2.0"
- 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"
- error-ex "^1.3.1"
- json-parse-even-better-errors "^2.3.0"
- lines-and-columns "^1.1.6"
-
-parseurl@~1.3.3:
- version "1.3.3"
- resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
- integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
-
-path-exists@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
- integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
-
-path-is-absolute@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
- integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
-
-path-key@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
- integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
-
-path-key@^3.0.0, path-key@^3.1.0:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
- integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
-
-path-parse@^1.0.6:
- version "1.0.7"
- resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
- integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
-
-path-to-regexp@0.1.7:
- version "0.1.7"
- resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
- integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=
-
-path-to-regexp@^1.8.0:
- version "1.8.0"
- resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a"
- integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==
- dependencies:
- isarray "0.0.1"
-
-path-type@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
- integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
-
-performance-now@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
- integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
-
-picomatch@^2.0.4, picomatch@^2.2.1:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
- integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==
-
-pkg-dir@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-5.0.0.tgz#a02d6aebe6ba133a928f74aec20bafdfe6b8e760"
- integrity sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==
- dependencies:
- find-up "^5.0.0"
-
-please-upgrade-node@^3.2.0:
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942"
- integrity sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==
- dependencies:
- semver-compare "^1.0.0"
-
-plist@^3.0.1:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/plist/-/plist-3.0.2.tgz#74bbf011124b90421c22d15779cee60060ba95bc"
- integrity sha512-MSrkwZBdQ6YapHy87/8hDU8MnIcyxBKjeF+McXnr5A9MtffPewTs7G3hlpodT5TacyfIyFTaJEhh3GGcmasTgQ==
- dependencies:
- base64-js "^1.5.1"
- xmlbuilder "^9.0.7"
- xmldom "^0.5.0"
-
-portfinder@^1.0.23:
- version "1.0.28"
- resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778"
- integrity sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==
- dependencies:
- async "^2.6.2"
- debug "^3.1.1"
- mkdirp "^0.5.5"
-
-prepend-http@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897"
- integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=
-
-prettier@^2.1.1:
- version "2.3.2"
- resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.3.2.tgz#ef280a05ec253712e486233db5c6f23441e7342d"
- integrity sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==
-
-pretty-quick@^3.0.0:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/pretty-quick/-/pretty-quick-3.1.1.tgz#93ca4e2dd38cc4e970e3f54a0ead317a25454688"
- integrity sha512-ZYLGiMoV2jcaas3vTJrLvKAYsxDoXQBUn8OSTxkl67Fyov9lyXivJTl0+2WVh+y6EovGcw7Lm5ThYpH+Sh3XxQ==
- dependencies:
- chalk "^3.0.0"
- execa "^4.0.0"
- find-up "^4.1.0"
- ignore "^5.1.4"
- mri "^1.1.5"
- multimatch "^4.0.0"
-
-process-nextick-args@~1.0.6:
- version "1.0.7"
- resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
- integrity sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=
-
-process-nextick-args@~2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
- integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
-
-progress@^2.0.3:
- version "2.0.3"
- 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.yarnpkg.com/promise-breaker/-/promise-breaker-5.0.0.tgz#58e8541f1619554057da95a211794d7834d30c1d"
- integrity sha512-mgsWQuG4kJ1dtO6e/QlNDLFtMkMzzecsC69aI5hlLEjGHFNpHrvGhFi4LiK5jg2SMQj74/diH+wZliL9LpGsyA==
-
-promise-inflight@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
- integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM=
-
-promise-retry@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-2.0.1.tgz#ff747a13620ab57ba688f5fc67855410c370da22"
- integrity sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==
- dependencies:
- err-code "^2.0.2"
- retry "^0.12.0"
-
-protobufjs@^6.10.0, protobufjs@^6.10.2, protobufjs@^6.8.1, protobufjs@^6.8.6, protobufjs@^6.8.8, protobufjs@^6.8.9:
- version "6.11.2"
- resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.2.tgz#de39fabd4ed32beaa08e9bb1e30d08544c1edf8b"
- integrity sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==
- dependencies:
- "@protobufjs/aspromise" "^1.1.2"
- "@protobufjs/base64" "^1.1.2"
- "@protobufjs/codegen" "^2.0.4"
- "@protobufjs/eventemitter" "^1.1.0"
- "@protobufjs/fetch" "^1.1.0"
- "@protobufjs/float" "^1.0.2"
- "@protobufjs/inquire" "^1.1.0"
- "@protobufjs/path" "^1.1.2"
- "@protobufjs/pool" "^1.1.0"
- "@protobufjs/utf8" "^1.1.0"
- "@types/long" "^4.0.1"
- "@types/node" ">=13.7.0"
- long "^4.0.0"
-
-proxy-addr@~2.0.5:
- version "2.0.7"
- 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"
- ipaddr.js "1.9.1"
-
-pseudomap@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
- integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM=
-
-psl@^1.1.28:
- version "1.8.0"
- resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24"
- integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==
-
-pump@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
- integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==
- dependencies:
- end-of-stream "^1.1.0"
- once "^1.3.1"
-
-pumpify@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-2.0.1.tgz#abfc7b5a621307c728b551decbbefb51f0e4aa1e"
- integrity sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw==
- dependencies:
- duplexify "^4.1.1"
- inherits "^2.0.3"
- pump "^3.0.0"
-
-punycode@^1.3.2:
- version "1.4.1"
- resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
- integrity sha1-wNWmOycYgArY4esPpSachN1BhF4=
-
-punycode@^2.1.0, punycode@^2.1.1:
- version "2.1.1"
- 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.yarnpkg.com/pupa/-/pupa-2.1.1.tgz#f5e8fd4afc2c5d97828faa523549ed8744a20d62"
- integrity sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==
- dependencies:
- escape-goat "^2.0.0"
-
-qs@6.7.0:
- version "6.7.0"
- resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
- integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==
-
-qs@^6.6.0:
- version "6.10.1"
- resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.1.tgz#4931482fa8d647a5aab799c5271d2133b981fb6a"
- integrity sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==
- dependencies:
- side-channel "^1.0.4"
-
-qs@~6.5.2:
- version "6.5.2"
- resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
- integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
-
-range-parser@~1.2.1:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
- integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
-
-raw-body@2.4.0:
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332"
- integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==
- dependencies:
- bytes "3.1.0"
- http-errors "1.7.2"
- iconv-lite "0.4.24"
- unpipe "1.0.0"
-
-raw-body@^2.3.3:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.1.tgz#30ac82f98bb5ae8c152e67149dac8d55153b168c"
- integrity sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==
- dependencies:
- bytes "3.1.0"
- http-errors "1.7.3"
- iconv-lite "0.4.24"
- unpipe "1.0.0"
-
-rc@^1.2.8:
- version "1.2.8"
- resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
- integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==
- dependencies:
- deep-extend "^0.6.0"
- ini "~1.3.0"
- minimist "^1.2.0"
- strip-json-comments "~2.0.1"
-
-re2@^1.15.8:
- version "1.16.0"
- resolved "https://registry.yarnpkg.com/re2/-/re2-1.16.0.tgz#f311eb4865b1296123800ea8e013cec8dab25590"
- integrity sha512-eizTZL2ZO0ZseLqfD4t3Qd0M3b3Nr0MBWpX81EbPMIud/1d/CSfUIx2GQK8fWiAeHoSekO5EOeFib2udTZLwYw==
- dependencies:
- install-artifact-from-github "^1.2.0"
- nan "^2.14.2"
- node-gyp "^8.0.0"
-
-readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.3.6, readable-stream@^2.3.7, readable-stream@~2.3.6:
- version "2.3.7"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
- integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
- dependencies:
- core-util-is "~1.0.0"
- inherits "~2.0.3"
- isarray "~1.0.0"
- process-nextick-args "~2.0.0"
- safe-buffer "~5.1.1"
- string_decoder "~1.1.1"
- util-deprecate "~1.0.1"
-
-readable-stream@^3.1.1, readable-stream@^3.4.0:
- version "3.6.0"
- 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.0:
- version "2.0.6"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e"
- integrity sha1-j5A0HmilPMySh4jaz80Rs265t44=
- dependencies:
- core-util-is "~1.0.0"
- inherits "~2.0.1"
- isarray "~1.0.0"
- process-nextick-args "~1.0.6"
- string_decoder "~0.10.x"
- util-deprecate "~1.0.1"
-
-readdirp@~3.6.0:
- version "3.6.0"
- resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
- integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
- dependencies:
- picomatch "^2.2.1"
-
-redeyed@~2.1.0:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/redeyed/-/redeyed-2.1.1.tgz#8984b5815d99cb220469c99eeeffe38913e6cc0b"
- integrity sha1-iYS1gV2ZyyIEacme7v/jiRPmzAs=
- dependencies:
- esprima "~4.0.0"
-
-registry-auth-token@^4.0.0:
- version "4.2.1"
- resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.1.tgz#6d7b4006441918972ccd5fedcd41dc322c79b250"
- integrity sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==
- dependencies:
- rc "^1.2.8"
-
-registry-url@^5.0.0:
- version "5.1.0"
- 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"
-
-request@^2.87.0, request@^2.88.2:
- version "2.88.2"
- resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
- integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==
- dependencies:
- 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"
-
-require-directory@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
- integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I=
-
-resolve-from@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
- integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
-
-resolve@^1.3.2:
- version "1.20.0"
- resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
- integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
- dependencies:
- is-core-module "^2.2.0"
- path-parse "^1.0.6"
-
-responselike@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7"
- integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=
- dependencies:
- lowercase-keys "^1.0.0"
-
-restore-cursor@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
- integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368=
- dependencies:
- onetime "^2.0.0"
- signal-exit "^3.0.2"
-
-retry-request@^4.0.0, retry-request@^4.2.2:
- version "4.2.2"
- resolved "https://registry.yarnpkg.com/retry-request/-/retry-request-4.2.2.tgz#b7d82210b6d2651ed249ba3497f07ea602f1a903"
- integrity sha512-xA93uxUD/rogV7BV59agW/JHPGXeREMWiZc9jhcwY4YdZ7QOtC7qbomYg0n4wyk2lJhggjvKvhNX8wln/Aldhg==
- dependencies:
- debug "^4.1.1"
- extend "^3.0.2"
-
-retry@0.12.0, retry@^0.12.0:
- version "0.12.0"
- resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b"
- integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=
-
-rimraf@2, rimraf@^2.2.8:
- version "2.7.1"
- 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.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
- integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
- dependencies:
- glob "^7.1.3"
-
-router@^1.3.1:
- version "1.3.5"
- resolved "https://registry.yarnpkg.com/router/-/router-1.3.5.tgz#cb2f47f74fd99a77fb3bc01cc947f46b79b1790f"
- integrity sha512-kozCJZUhuSJ5VcLhSb3F8fsmGXy+8HaDbKCAerR1G6tq3mnMZFMuSohbFvGv1c5oMFipijDjRZuuN/Sq5nMf3g==
- dependencies:
- array-flatten "3.0.0"
- debug "2.6.9"
- methods "~1.1.2"
- parseurl "~1.3.3"
- path-to-regexp "0.1.7"
- setprototypeof "1.2.0"
- utils-merge "1.0.1"
-
-rsvp@^4.8.5:
- version "4.8.5"
- resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734"
- integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==
-
-run-async@^2.2.0:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
- integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==
-
-rxjs@^6.4.0:
- version "6.6.7"
- 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:
- version "5.1.2"
- resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
- integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
-
-safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0:
- version "5.2.1"
- resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
- integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
-
-"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
- integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
-
-semver-compare@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc"
- integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w=
-
-semver-diff@^3.1.1:
- version "3.1.1"
- 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-regex@^3.1.2:
- version "3.1.2"
- resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-3.1.2.tgz#34b4c0d361eef262e07199dbef316d0f2ab11807"
- integrity sha512-bXWyL6EAKOJa81XG1OZ/Yyuq+oT0b2YLlxx7c+mrdYPaPbnj6WgVULXhinMIeZGufuUBu/eVRqXEhiv4imfwxA==
-
-semver@^5.0.1, semver@^5.3.0, semver@^5.5.0, semver@^5.6.0, semver@^5.7.1:
- version "5.7.1"
- resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
- integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
-
-semver@^6.0.0, semver@^6.2.0, semver@^6.3.0:
- version "6.3.0"
- resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
- integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
-
-semver@^7.0.0, semver@^7.3.5:
- version "7.3.5"
- resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7"
- integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==
- dependencies:
- lru-cache "^6.0.0"
-
-send@0.17.1:
- version "0.17.1"
- resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8"
- 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"
-
-serve-static@1.14.1:
- version "1.14.1"
- resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9"
- integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==
- dependencies:
- encodeurl "~1.0.2"
- escape-html "~1.0.3"
- parseurl "~1.3.3"
- send "0.17.1"
-
-set-blocking@~2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
- integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
-
-setimmediate@~1.0.4:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
- integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=
-
-setprototypeof@1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683"
- integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==
-
-setprototypeof@1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
- integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==
-
-shebang-command@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
- integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=
- dependencies:
- shebang-regex "^1.0.0"
-
-shebang-command@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
- integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
- dependencies:
- shebang-regex "^3.0.0"
-
-shebang-regex@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
- integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
-
-shebang-regex@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
- integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
-
-side-channel@^1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
- integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==
- dependencies:
- call-bind "^1.0.0"
- get-intrinsic "^1.0.2"
- object-inspect "^1.9.0"
-
-signal-exit@^3.0.0, signal-exit@^3.0.2:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
- integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
-
-simple-swizzle@^0.2.2:
- version "0.2.2"
- resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a"
- integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=
- dependencies:
- is-arrayish "^0.3.1"
-
-slash@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
- integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
-
-smart-buffer@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.1.0.tgz#91605c25d91652f4661ea69ccf45f1b331ca21ba"
- integrity sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==
-
-snakeize@^0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/snakeize/-/snakeize-0.1.0.tgz#10c088d8b58eb076b3229bb5a04e232ce126422d"
- integrity sha1-EMCI2LWOsHazIpu1oE4jLOEmQi0=
-
-socks-proxy-agent@^5.0.0:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-5.0.1.tgz#032fb583048a29ebffec2e6a73fca0761f48177e"
- integrity sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ==
- dependencies:
- agent-base "^6.0.2"
- debug "4"
- socks "^2.3.3"
-
-socks@^2.3.3:
- version "2.6.1"
- resolved "https://registry.yarnpkg.com/socks/-/socks-2.6.1.tgz#989e6534a07cf337deb1b1c94aaa44296520d30e"
- integrity sha512-kLQ9N5ucj8uIcxrDwjm0Jsqk06xdpBjGNQtpXy4Q8/QY2k+fY7nZH8CARy+hkbG+SGAovmzzuauCpBlb8FrnBA==
- dependencies:
- ip "^1.1.5"
- smart-buffer "^4.1.0"
-
-source-map-support@^0.5.17:
- version "0.5.19"
- resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61"
- integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==
- dependencies:
- buffer-from "^1.0.0"
- source-map "^0.6.0"
-
-source-map@^0.6.0:
- version "0.6.1"
- resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
- integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
-
-sprintf-js@~1.0.2:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
- integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
-
-sshpk@^1.7.0:
- version "1.16.1"
- resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
- integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==
- dependencies:
- 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@^8.0.0, ssri@^8.0.1:
- version "8.0.1"
- resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.1.tgz#638e4e439e2ffbd2cd289776d5ca457c4f51a2af"
- integrity sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==
- dependencies:
- minipass "^3.1.1"
-
-stack-trace@0.0.x:
- version "0.0.10"
- resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0"
- integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=
-
-"statuses@>= 1.5.0 < 2", statuses@~1.5.0:
- version "1.5.0"
- resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
- integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
-
-stream-events@^1.0.1, stream-events@^1.0.4, stream-events@^1.0.5:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/stream-events/-/stream-events-1.0.5.tgz#bbc898ec4df33a4902d892333d47da9bf1c406d5"
- integrity sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==
- dependencies:
- stubs "^3.0.0"
-
-stream-shift@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d"
- integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==
-
-streamsearch@0.1.2:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a"
- integrity sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=
-
-string-length@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/string-length/-/string-length-1.0.1.tgz#56970fb1c38558e9e70b728bf3de269ac45adfac"
- integrity sha1-VpcPscOFWOnnC3KL894mmsRa36w=
- dependencies:
- strip-ansi "^3.0.0"
-
-string-width@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
- integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=
- dependencies:
- code-point-at "^1.0.0"
- is-fullwidth-code-point "^1.0.0"
- strip-ansi "^3.0.0"
-
-"string-width@^1.0.2 || 2", string-width@^2.1.0:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
- integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==
- dependencies:
- is-fullwidth-code-point "^2.0.0"
- strip-ansi "^4.0.0"
-
-string-width@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961"
- 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.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5"
- integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==
- dependencies:
- emoji-regex "^8.0.0"
- is-fullwidth-code-point "^3.0.0"
- strip-ansi "^6.0.0"
-
-string_decoder@^1.1.1:
- version "1.3.0"
- 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"
-
-string_decoder@~0.10.x:
- version "0.10.31"
- resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
- integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=
-
-string_decoder@~1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
- integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
- dependencies:
- safe-buffer "~5.1.0"
-
-strip-ansi@^3.0.0, strip-ansi@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
- integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=
- dependencies:
- ansi-regex "^2.0.0"
-
-strip-ansi@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
- integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8=
- dependencies:
- ansi-regex "^3.0.0"
-
-strip-ansi@^5.1.0, strip-ansi@^5.2.0:
- version "5.2.0"
- resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae"
- integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==
- dependencies:
- ansi-regex "^4.1.0"
-
-strip-ansi@^6.0.0:
- version "6.0.0"
- resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532"
- integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==
- dependencies:
- ansi-regex "^5.0.0"
-
-strip-final-newline@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad"
- integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
-
-strip-json-comments@~2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
- integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
-
-stubs@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/stubs/-/stubs-3.0.0.tgz#e8d2ba1fa9c90570303c030b6900f7d5f89abe5b"
- integrity sha1-6NK6H6nJBXAwPAMLaQD31fiavls=
-
-superstatic@^7.1.0:
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/superstatic/-/superstatic-7.1.0.tgz#42cc773a0f500fb691841e0533d0b8c31f25997f"
- integrity sha512-yBU8iw07nM3Bu4jFc8lnKwLey0cj61OaGmFJZcYC2X+kEpXVmXzERJ3OTAHZAESe1OTeNIuWadt81U5IULGGAA==
- dependencies:
- basic-auth-connect "^1.0.0"
- chalk "^1.1.3"
- compare-semver "^1.0.0"
- compression "^1.7.0"
- connect "^3.6.2"
- destroy "^1.0.4"
- fast-url-parser "^1.1.3"
- fs-extra "^8.1.0"
- glob-slasher "^1.0.1"
- home-dir "^1.0.0"
- is-url "^1.2.2"
- join-path "^1.1.1"
- lodash "^4.17.19"
- mime-types "^2.1.16"
- minimatch "^3.0.4"
- morgan "^1.8.2"
- nash "^3.0.0"
- on-finished "^2.2.0"
- on-headers "^1.0.0"
- path-to-regexp "^1.8.0"
- router "^1.3.1"
- rsvp "^4.8.5"
- string-length "^1.0.0"
- update-notifier "^4.1.1"
- optionalDependencies:
- re2 "^1.15.8"
-
-supports-color@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
- integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=
-
-supports-color@^5.0.0, supports-color@^5.3.0:
- version "5.5.0"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
- integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
- dependencies:
- has-flag "^3.0.0"
-
-supports-color@^7.1.0:
- version "7.2.0"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
- integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
- dependencies:
- has-flag "^4.0.0"
-
-supports-hyperlinks@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-1.0.1.tgz#71daedf36cc1060ac5100c351bb3da48c29c0ef7"
- integrity sha512-HHi5kVSefKaJkGYXbDuKbUGRVxqnWGn3J2e39CYcNJEfWciGq2zYtOhXLTlvrOZW1QU7VX67w7fMmWafHX9Pfw==
- dependencies:
- has-flag "^2.0.0"
- supports-color "^5.0.0"
-
-tar-stream@^2.1.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287"
- 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"
-
-tar@^4.3.0:
- version "4.4.15"
- resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.15.tgz#3caced4f39ebd46ddda4d6203d48493a919697f8"
- integrity sha512-ItbufpujXkry7bHH9NpQyTXPbJ72iTlXgkBAYsAjDXk3Ds8t/3NfO5P4xZGy7u+sYuQUbimgzswX4uQIEeNVOA==
- dependencies:
- chownr "^1.1.1"
- fs-minipass "^1.2.5"
- minipass "^2.8.6"
- minizlib "^1.2.1"
- mkdirp "^0.5.0"
- safe-buffer "^5.1.2"
- yallist "^3.0.3"
-
-tar@^6.0.2, tar@^6.1.0:
- version "6.1.2"
- resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.2.tgz#1f045a90a6eb23557a603595f41a16c57d47adc6"
- integrity sha512-EwKEgqJ7nJoS+s8QfLYVGMDmAsj+StbI2AM/RTHeUSsOw6Z8bwNBRv5z3CY0m7laC5qUAqruLX5AhMuc5deY3Q==
- 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"
-
-tcp-port-used@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/tcp-port-used/-/tcp-port-used-1.0.2.tgz#9652b7436eb1f4cfae111c79b558a25769f6faea"
- integrity sha512-l7ar8lLUD3XS1V2lfoJlCBaeoaWo/2xfYt81hM7VlvR4RrMVFqfmzfhLVk40hAb368uitje5gPtBRL1m/DGvLA==
- dependencies:
- debug "4.3.1"
- is2 "^2.0.6"
-
-teeny-request@^7.0.0:
- version "7.1.1"
- resolved "https://registry.yarnpkg.com/teeny-request/-/teeny-request-7.1.1.tgz#2b0d156f4a8ad81de44303302ba8d7f1f05e20e6"
- integrity sha512-iwY6rkW5DDGq8hE2YgNQlKbptYpY5Nn2xecjQiNjOXWbKzPGUfmeUBCSQbbr306d7Z7U2N0TPl+/SwYRfua1Dg==
- dependencies:
- http-proxy-agent "^4.0.0"
- https-proxy-agent "^5.0.0"
- node-fetch "^2.6.1"
- stream-events "^1.0.5"
- uuid "^8.0.0"
-
-term-size@^2.1.0:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.1.tgz#2a6a54840432c2fb6320fea0f415531e90189f54"
- integrity sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==
-
-text-hex@1.0.x:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5"
- integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==
-
-through2@2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.1.tgz#384e75314d49f32de12eebb8136b8eb6b5d59da9"
- integrity sha1-OE51MU1J8y3hLuu4E2uOtrXVnak=
- dependencies:
- readable-stream "~2.0.0"
- xtend "~4.0.0"
-
-"through@>=2.2.7 <3", through@^2.3.6:
- version "2.3.8"
- resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
- integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
-
-timers-ext@^0.1.5, timers-ext@^0.1.7:
- version "0.1.7"
- resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.7.tgz#6f57ad8578e07a3fb9f91d9387d65647555e25c6"
- integrity sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==
- dependencies:
- es5-ext "~0.10.46"
- next-tick "1"
-
-tmp@0.0.33, tmp@^0.0.33:
- version "0.0.33"
- resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
- integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
- dependencies:
- os-tmpdir "~1.0.2"
-
-to-readable-stream@^1.0.0:
- version "1.0.0"
- 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@^5.0.1:
- version "5.0.1"
- 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"
-
-toidentifier@1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
- integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
-
-tough-cookie@~2.5.0:
- version "2.5.0"
- resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
- integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==
- dependencies:
- psl "^1.1.28"
- punycode "^2.1.1"
-
-toxic@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/toxic/-/toxic-1.0.1.tgz#8c2e2528da591100adc3883f2c0e56acfb1c7288"
- integrity sha512-WI3rIGdcaKULYg7KVoB0zcjikqvcYYvcuT6D89bFPz2rVR0Rl0PK6x8/X62rtdLtBKIE985NzVf/auTtGegIIg==
- dependencies:
- lodash "^4.17.10"
-
-"traverse@>=0.3.0 <0.4":
- version "0.3.9"
- resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.3.9.tgz#717b8f220cc0bb7b44e40514c22b2e8bbc70d8b9"
- integrity sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=
-
-triple-beam@^1.2.0, triple-beam@^1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9"
- integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==
-
-ts-node@^8.6.2:
- version "8.10.2"
- resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.10.2.tgz#eee03764633b1234ddd37f8db9ec10b75ec7fb8d"
- integrity sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==
- dependencies:
- arg "^4.1.0"
- diff "^4.0.1"
- make-error "^1.1.1"
- source-map-support "^0.5.17"
- yn "3.1.1"
-
-tslib@^1.13.0, tslib@^1.8.1, tslib@^1.9.0:
- version "1.14.1"
- resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
- integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
-
-tslib@^2.1.0, tslib@^2.2.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e"
- integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==
-
-tslint@^6.1.0:
- version "6.1.3"
- resolved "https://registry.yarnpkg.com/tslint/-/tslint-6.1.3.tgz#5c23b2eccc32487d5523bd3a470e9aa31789d904"
- integrity sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==
- dependencies:
- "@babel/code-frame" "^7.0.0"
- builtin-modules "^1.1.1"
- chalk "^2.3.0"
- commander "^2.12.1"
- diff "^4.0.1"
- glob "^7.1.1"
- js-yaml "^3.13.1"
- minimatch "^3.0.4"
- mkdirp "^0.5.3"
- resolve "^1.3.2"
- semver "^5.3.0"
- tslib "^1.13.0"
- tsutils "^2.29.0"
-
-tsutils@^2.29.0:
- version "2.29.0"
- resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99"
- integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==
- dependencies:
- tslib "^1.8.1"
-
-tunnel-agent@^0.6.0:
- version "0.6.0"
- resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
- integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=
- dependencies:
- safe-buffer "^5.0.1"
-
-tweetnacl@^0.14.3, tweetnacl@~0.14.0:
- version "0.14.5"
- resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
- integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
-
-tweetnacl@^1.0.1:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596"
- integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==
-
-tweetsodium@0.0.5:
- version "0.0.5"
- resolved "https://registry.yarnpkg.com/tweetsodium/-/tweetsodium-0.0.5.tgz#f63ab4b1d26d6355d82d512a2bbf03cae96eb3e8"
- integrity sha512-T3aXZtx7KqQbutTtBfn+P5By3HdBuB1eCoGviIrRJV2sXeToxv2X2cv5RvYqgG26PSnN5m3fYixds22Gkfd11w==
- dependencies:
- blakejs "^1.1.0"
- tweetnacl "^1.0.1"
-
-type-fest@^0.8.1:
- version "0.8.1"
- resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
- integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
-
-type-is@~1.6.17, type-is@~1.6.18:
- version "1.6.18"
- 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"
- mime-types "~2.1.24"
-
-type@^1.0.1:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0"
- integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==
-
-type@^2.0.0:
- version "2.5.0"
- resolved "https://registry.yarnpkg.com/type/-/type-2.5.0.tgz#0a2e78c2e77907b252abe5f298c1b01c63f0db3d"
- integrity sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw==
-
-typedarray-to-buffer@^3.1.5:
- version "3.1.5"
- resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080"
- integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==
- dependencies:
- is-typedarray "^1.0.0"
-
-typescript@^3.2.2:
- version "3.9.10"
- resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.10.tgz#70f3910ac7a51ed6bef79da7800690b19bf778b8"
- integrity sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==
-
-unique-filename@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230"
- integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==
- dependencies:
- unique-slug "^2.0.0"
-
-unique-slug@^2.0.0:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c"
- integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==
- dependencies:
- imurmurhash "^0.1.4"
-
-unique-string@^2.0.0:
- version "2.0.0"
- 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"
-
-universal-analytics@^0.4.16:
- version "0.4.23"
- resolved "https://registry.yarnpkg.com/universal-analytics/-/universal-analytics-0.4.23.tgz#d915e676850c25c4156762471bdd7cf2eaaca8ac"
- integrity sha512-lgMIH7XBI6OgYn1woDEmxhGdj8yDefMKg7GkWdeATAlQZFrMrNyxSkpDzY57iY0/6fdlzTbBV03OawvvzG+q7A==
- dependencies:
- debug "^4.1.1"
- request "^2.88.2"
- uuid "^3.0.0"
-
-universalify@^0.1.0:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
- integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
-
-unpipe@1.0.0, unpipe@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
- integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=
-
-unzipper@^0.10.10:
- version "0.10.11"
- resolved "https://registry.yarnpkg.com/unzipper/-/unzipper-0.10.11.tgz#0b4991446472cbdb92ee7403909f26c2419c782e"
- integrity sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==
- dependencies:
- big-integer "^1.6.17"
- binary "~0.3.0"
- bluebird "~3.4.1"
- buffer-indexof-polyfill "~1.0.0"
- duplexer2 "~0.1.4"
- fstream "^1.0.12"
- graceful-fs "^4.2.2"
- listenercount "~1.0.1"
- readable-stream "~2.3.6"
- setimmediate "~1.0.4"
-
-update-notifier@^4.1.0, update-notifier@^4.1.1:
- version "4.1.3"
- resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-4.1.3.tgz#be86ee13e8ce48fb50043ff72057b5bd598e1ea3"
- integrity sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A==
- 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"
-
-uri-js@^4.2.2:
- version "4.4.1"
- resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
- integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
- dependencies:
- punycode "^2.1.0"
-
-url-join@0.0.1:
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/url-join/-/url-join-0.0.1.tgz#1db48ad422d3402469a87f7d97bdebfe4fb1e3c8"
- integrity sha1-HbSK1CLTQCRpqH99l73r/k+x48g=
-
-url-parse-lax@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c"
- integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=
- dependencies:
- prepend-http "^2.0.0"
-
-util-deprecate@^1.0.1, util-deprecate@~1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
- integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
-
-utils-merge@1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
- integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
-
-uuid@^3.0.0, uuid@^3.3.2:
- version "3.4.0"
- resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
- integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
-
-uuid@^8.0.0:
- version "8.3.2"
- resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
- integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
-
-valid-url@^1:
- version "1.0.9"
- resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200"
- integrity sha1-HBRHm0DxOXp1eC8RXkCGRHQzogA=
-
-vary@^1, vary@~1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
- integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
-
-verror@1.10.0:
- version "1.10.0"
- resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
- integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=
- dependencies:
- assert-plus "^1.0.0"
- core-util-is "1.0.2"
- extsprintf "^1.2.0"
-
-walkdir@^0.4.0:
- version "0.4.1"
- resolved "https://registry.yarnpkg.com/walkdir/-/walkdir-0.4.1.tgz#dc119f83f4421df52e3061e514228a2db20afa39"
- integrity sha512-3eBwRyEln6E1MSzcxcVpQIhRG8Q1jLvEqRmCZqS3dsfXEDR/AhOF4d+jHg1qvDCpYaVRZjENPQyrVxAkQqxPgQ==
-
-wcwidth@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8"
- integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=
- dependencies:
- defaults "^1.0.3"
-
-websocket-driver@>=0.5.1:
- version "0.7.4"
- resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760"
- integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==
- dependencies:
- http-parser-js ">=0.5.1"
- safe-buffer ">=5.1.0"
- websocket-extensions ">=0.1.1"
-
-websocket-extensions@>=0.1.1:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42"
- integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==
-
-which-pm-runs@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb"
- integrity sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=
-
-which@^1.2.9:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
- integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
- dependencies:
- isexe "^2.0.0"
-
-which@^2.0.1, which@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
- integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
- dependencies:
- isexe "^2.0.0"
-
-wide-align@^1.1.0:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457"
- integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==
- dependencies:
- string-width "^1.0.2 || 2"
-
-widest-line@^3.1.0:
- version "3.1.0"
- 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"
-
-winston-transport@^4.4.0:
- version "4.4.0"
- resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.4.0.tgz#17af518daa690d5b2ecccaa7acf7b20ca7925e59"
- integrity sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw==
- dependencies:
- readable-stream "^2.3.7"
- triple-beam "^1.2.0"
-
-winston@^3.0.0:
- version "3.3.3"
- resolved "https://registry.yarnpkg.com/winston/-/winston-3.3.3.tgz#ae6172042cafb29786afa3d09c8ff833ab7c9170"
- integrity sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==
- dependencies:
- "@dabh/diagnostics" "^2.0.2"
- async "^3.1.0"
- is-stream "^2.0.0"
- logform "^2.2.0"
- one-time "^1.0.0"
- readable-stream "^3.4.0"
- stack-trace "0.0.x"
- triple-beam "^1.3.0"
- winston-transport "^4.4.0"
-
-wrap-ansi@^7.0.0:
- version "7.0.0"
- 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"
- string-width "^4.1.0"
- strip-ansi "^6.0.0"
-
-wrappy@1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
- integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
-
-write-file-atomic@^3.0.0:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8"
- integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==
- dependencies:
- imurmurhash "^0.1.4"
- is-typedarray "^1.0.0"
- signal-exit "^3.0.2"
- typedarray-to-buffer "^3.1.5"
-
-ws@^7.2.3:
- version "7.5.3"
- resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.3.tgz#160835b63c7d97bfab418fc1b8a9fced2ac01a74"
- integrity sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==
-
-xdg-basedir@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13"
- integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==
-
-xmlbuilder@^9.0.7:
- version "9.0.7"
- resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d"
- integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=
-
-xmldom@^0.5.0:
- version "0.5.0"
- resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.5.0.tgz#193cb96b84aa3486127ea6272c4596354cb4962e"
- integrity sha512-Foaj5FXVzgn7xFzsKeNIde9g6aFBxTPi37iwsno8QvApmtg7KYrr+OPyRHcJF7dud2a5nGRBXK3n0dL62Gf7PA==
-
-xtend@~4.0.0:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
- integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
-
-y18n@^5.0.5:
- version "5.0.8"
- resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
- integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
-
-yallist@^2.0.0:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
- integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=
-
-yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
- integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
-
-yallist@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
- integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
-
-yaml@^1.10.0:
- version "1.10.2"
- resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
- integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
-
-yargs-parser@^20.2.2:
- version "20.2.9"
- resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
- integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
-
-yargs@^16.1.1:
- version "16.2.0"
- resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"
- 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"
-
-yn@3.1.1:
- version "3.1.1"
- 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==
-
-zip-stream@^2.1.2:
- version "2.1.3"
- resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-2.1.3.tgz#26cc4bdb93641a8590dd07112e1f77af1758865b"
- integrity sha512-EkXc2JGcKhO5N5aZ7TmuNo45budRaFGHOmz24wtJR7znbNqDPmdZtUauKX6et8KAVseAMBOyWJqEpXcHTBsh7Q==
- dependencies:
- archiver-utils "^2.1.0"
- compress-commons "^2.1.1"
- readable-stream "^3.4.0"
diff --git a/ft_actions/yarn.lock b/ft_actions/yarn.lock
deleted file mode 100644
index fb57ccd13..000000000
--- a/ft_actions/yarn.lock
+++ /dev/null
@@ -1,4 +0,0 @@
-# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
-# yarn lockfile v1
-
-
diff --git a/ft_build/compiler/index.ts b/ft_build/compiler/index.ts
deleted file mode 100644
index 9b45f61f2..000000000
--- a/ft_build/compiler/index.ts
+++ /dev/null
@@ -1,80 +0,0 @@
-import { addPackages, addExtensionLib, asyncExecute } from "./terminal";
-const fs = require("fs");
-import { generateConfigFromTableSchema } from "./loader";
-import { commandErrorHandler } from "../utils";
-const path = require("path");
-import admin from "firebase-admin";
-
-export default async function generateConfig(
- schemaPath: string,
- user: admin.auth.UserRecord,
- streamLogger
-) {
- return await generateConfigFromTableSchema(
- schemaPath,
- user,
- streamLogger
- ).then(async (success) => {
- if (!success) {
- await streamLogger.info(
- `generateConfigFromTableSchema failed to complete`
- );
- return false;
- }
-
- await streamLogger.info(`generateConfigFromTableSchema done`);
- const configFile = fs.readFileSync(
- path.resolve(__dirname, "../functions/src/functionConfig.ts"),
- "utf-8"
- );
- await streamLogger.info(`configFile: ${JSON.stringify(configFile)}`);
- const requiredDependencies = configFile.match(
- /(?<=(require\(("|'))).*?(?=("|')\))/g
- );
- if (requiredDependencies) {
- const packgesAdded = await addPackages(
- requiredDependencies.map((p: any) => ({ name: p })),
- user,
- streamLogger
- );
- if (!packgesAdded) {
- return false;
- }
- }
- await streamLogger.info(
- `requiredDependencies: ${JSON.stringify(requiredDependencies)}`
- );
-
- const isFunctionConfigValid = await asyncExecute(
- "cd build/functions/src; tsc functionConfig.ts",
- commandErrorHandler(
- {
- user,
- functionConfigTs: configFile,
- description: `Invalid compiled functionConfig.ts`,
- },
- streamLogger
- )
- );
- await streamLogger.info(
- `isFunctionConfigValid: ${JSON.stringify(isFunctionConfigValid)}`
- );
- if (!isFunctionConfigValid) {
- return false;
- }
-
- const { extensionsConfig } = require("../functions/src/functionConfig.js");
- const requiredExtensions = extensionsConfig.map((s: any) => s.type);
- await streamLogger.info(
- `requiredExtensions: ${JSON.stringify(requiredExtensions)}`
- );
-
- for (const lib of requiredExtensions) {
- const success = await addExtensionLib(lib, user, streamLogger);
- if (!success) {
- return false;
- }
- }
- return true;
- });
-}
diff --git a/ft_build/compiler/loader.ts b/ft_build/compiler/loader.ts
deleted file mode 100644
index 4cb2a1826..000000000
--- a/ft_build/compiler/loader.ts
+++ /dev/null
@@ -1,209 +0,0 @@
-import { db } from "../firebaseConfig";
-const fs = require("fs");
-const beautify = require("js-beautify").js;
-import admin from "firebase-admin";
-import { parseExtensionsConfig } from "../utils";
-
-export const generateConfigFromTableSchema = async (
- schemaDocPath: string,
- user: admin.auth.UserRecord,
- streamLogger
-) => {
- await streamLogger.info("getting schema...");
- const schemaDoc = await db.doc(schemaDocPath).get();
- const schemaData = schemaDoc.data();
- try {
- if (!schemaData) throw new Error("no schema found");
-
- // Temporarily disabled because this is super long
- // await streamLogger.info(`schemaData: ${JSON.stringify(schemaData)}`);
- const derivativeColumns = Object.values(schemaData.columns).filter(
- (col: any) => col.type === "DERIVATIVE"
- );
- await streamLogger.info(
- `derivativeColumns: ${JSON.stringify(derivativeColumns)}`
- );
- const derivativesConfig = `[${derivativeColumns.reduce(
- (acc, currColumn: any) => {
- if (
- !currColumn.config.listenerFields ||
- currColumn.config.listenerFields.length === 0
- )
- throw new Error(
- `${currColumn.key} derivative is missing listener fields`
- );
- if (currColumn.config.listenerFields.includes(currColumn.key))
- throw new Error(
- `${currColumn.key} derivative has its own key as a listener field`
- );
- return `${acc}{\nfieldName:'${
- currColumn.key
- }',evaluate:async ({row,ref,db,auth,storage,utilFns}) =>{${
- currColumn.config.script
- }},\nlistenerFields:[${currColumn.config.listenerFields
- .map((fieldKey: string) => `"${fieldKey}"`)
- .join(",\n")}]},\n`;
- },
- ""
- )}]`;
- await streamLogger.info(
- `derivativesConfig: ${JSON.stringify(derivativesConfig)}`
- );
-
- const initializableColumns = Object.values(
- schemaData.columns
- ).filter((col: any) => Boolean(col.config?.defaultValue));
- await streamLogger.info(
- `initializableColumns: ${JSON.stringify(initializableColumns)}`
- );
- const initializeConfig = `[${initializableColumns.reduce(
- (acc, currColumn: any) => {
- if (currColumn.config.defaultValue.type === "static") {
- return `${acc}{\nfieldName:'${currColumn.key}',
- type:"${currColumn.config.defaultValue.type}",
- value:${
- typeof currColumn.config.defaultValue.value === "string"
- ? `"${currColumn.config.defaultValue.value}"`
- : JSON.stringify(currColumn.config.defaultValue.value)
- },
- },\n`;
- } else if (currColumn.config.defaultValue.type === "dynamic") {
- return `${acc}{\nfieldName:'${currColumn.key}',
- type:"${currColumn.config.defaultValue.type}",
- script:async ({row,ref,db,auth,utilFns}) =>{${currColumn.config.defaultValue.script}},
- },\n`;
- } else {
- return `${acc}{\nfieldName:'${currColumn.key}',
- type:"${currColumn.config.defaultValue.type}"
- },\n`;
- }
- },
- ""
- )}]`;
- await streamLogger.info(
- `initializeConfig: ${JSON.stringify(initializeConfig)}`
- );
- const documentSelectColumns = Object.values(schemaData.columns).filter(
- (col: any) => col.type === "DOCUMENT_SELECT" && col.config?.trackedFields
- );
- const documentSelectConfig = `[${documentSelectColumns.reduce(
- (acc, currColumn: any) => {
- return `${acc}{\nfieldName:'${
- currColumn.key
- }',\ntrackedFields:[${currColumn.config.trackedFields
- .map((fieldKey: string) => `"${fieldKey}"`)
- .join(",\n")}]},\n`;
- },
- ""
- )}]`;
- await streamLogger.info(
- `documentSelectColumns: ${JSON.stringify(documentSelectColumns)}`
- );
-
- const extensionsConfig = parseExtensionsConfig(
- schemaData.extensions,
- user,
- streamLogger
- );
- await streamLogger.info(
- `extensionsConfig: ${JSON.stringify(extensionsConfig)}`
- );
-
- const collectionType = schemaDocPath.includes("subTables")
- ? "subCollection"
- : schemaDocPath.includes("groupSchema")
- ? "groupCollection"
- : "collection";
- let collectionId = "";
- let functionName = "";
- let triggerPath = "";
- switch (collectionType) {
- case "collection":
- collectionId = schemaDocPath.split("/").pop() ?? "";
- functionName = `"${collectionId}"`;
- triggerPath = `"${collectionId}/{docId}"`;
- break;
- case "subCollection":
- let pathParentIncrement = 0;
- triggerPath =
- '"' +
- schemaDocPath
- .replace("_FIRETABLE_/settings/schema/", "")
- .replace(/subTables/g, function () {
- pathParentIncrement++;
- return `{parentDoc${pathParentIncrement}}`;
- }) +
- "/{docId}" +
- '"';
- functionName =
- '"' +
- schemaDocPath
- .replace("_FIRETABLE_/settings/schema/", "")
- .replace(/\/subTables\//g, "_") +
- '"';
- break;
- case "groupCollection":
- collectionId = schemaDocPath.split("/").pop() ?? "";
- const triggerDepth = schemaData.triggerDepth
- ? schemaData.triggerDepth
- : 1;
- triggerPath = "";
- for (let i = 1; i <= triggerDepth; i++) {
- triggerPath = triggerPath + `{parentCol${i}}/{parentDoc${i}}/`;
- }
- triggerPath = '"' + triggerPath + collectionId + "/" + "{docId}" + '"';
- functionName = `"CG_${collectionId}${
- triggerDepth > 1 ? `_D${triggerDepth}` : ""
- }"`;
- break;
- default:
- break;
- }
- await streamLogger.info(
- `collectionType: ${JSON.stringify(collectionType)}`
- );
-
- // generate field types from table meta data
- const fieldTypes = JSON.stringify(
- Object.keys(schemaData.columns).reduce((acc, cur) => {
- const field = schemaData.columns[cur];
- let fieldType = field.type;
- if (fieldType === "DERIVATIVE") {
- fieldType = field.config.renderFieldType;
- }
- return {
- [cur]: fieldType,
- ...acc,
- };
- }, {})
- );
- await streamLogger.info(`fieldTypes: ${JSON.stringify(fieldTypes)}`);
-
- const exports: any = {
- fieldTypes,
- triggerPath,
- functionName: functionName.replace(/-/g, "_"),
- derivativesConfig,
- initializeConfig,
- documentSelectConfig,
- extensionsConfig,
- };
- await streamLogger.info(`exports: ${JSON.stringify(exports)}`);
-
- const fileData = Object.keys(exports).reduce((acc, currKey) => {
- return `${acc}\nexport const ${currKey} = ${exports[currKey]}`;
- }, ``);
- await streamLogger.info(`fileData: ${JSON.stringify(fileData)}`);
-
- const path = require("path");
- fs.writeFileSync(
- path.resolve(__dirname, "../functions/src/functionConfig.ts"),
- beautify(fileData, { indent_size: 2 })
- );
-
- return true;
- } catch (error) {
- streamLogger.error(error.message);
- return false;
- }
-};
diff --git a/ft_build/compiler/terminal.ts b/ft_build/compiler/terminal.ts
deleted file mode 100644
index 6a002e9d0..000000000
--- a/ft_build/compiler/terminal.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-import * as child from "child_process";
-import admin from "firebase-admin";
-import { commandErrorHandler, logErrorToDB } from "../utils";
-
-function execute(command: string, callback: any) {
- console.log(command);
- child.exec(command, function (error, stdout, stderr) {
- console.log({ error, stdout, stderr });
- callback(stdout);
- });
-}
-
-export const asyncExecute = async (command: string, callback: any) =>
- new Promise(async (resolve, reject) => {
- child.exec(command, async function (error, stdout, stderr) {
- console.log({ error, stdout, stderr });
- await callback(error, stdout, stderr);
- resolve(!error);
- });
- });
-
-export const addPackages = async (
- packages: { name: string; version?: string }[],
- user: admin.auth.UserRecord,
- streamLogger
-) => {
- const packagesString = packages.reduce((acc, currPackage) => {
- return `${acc} ${currPackage.name}@${currPackage.version ?? "latest"}`;
- }, "");
- if (packagesString.trim().length !== 0) {
- const success = await asyncExecute(
- `cd build/functions;yarn add ${packagesString}`,
- commandErrorHandler(
- {
- user,
- description: "Error adding packages",
- },
- streamLogger
- )
- );
- return success;
- }
- return true;
-};
-
-export const addExtensionLib = async (
- name: string,
- user: admin.auth.UserRecord,
- streamLogger
-) => {
- try {
- const { dependencies } = require(`../extensionsLib/${name}`);
- const packages = Object.keys(dependencies).map((key) => ({
- name: key,
- version: dependencies[key],
- }));
- const success = await addPackages(packages, user, streamLogger);
- if (!success) {
- return false;
- }
- } catch (error) {
- logErrorToDB(
- {
- user,
- errorDescription: "Error parsing dependencies",
- },
- streamLogger
- );
- return false;
- }
-
- const success = await asyncExecute(
- `cp build/extensionsLib/${name}.ts build/functions/src/extensions/${name}.ts`,
- commandErrorHandler(
- {
- user,
- description: "Error copying extensionsLib",
- },
- streamLogger
- )
- );
- return success;
-};
diff --git a/ft_build/compiler/tsconfig.json b/ft_build/compiler/tsconfig.json
deleted file mode 100644
index 597010922..000000000
--- a/ft_build/compiler/tsconfig.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "compilerOptions": {
- "module": "commonjs",
- "noImplicitReturns": true,
- "noUnusedLocals": true,
- "outDir": "lib",
- "sourceMap": true,
- "strict": true,
- "noImplicitAny": false,
- "resolveJsonModule": true,
- "target": "es6",
- "lib": ["ESNext"],
- "strictNullChecks": false
- },
- "compileOnSave": true,
- "include": ["src", "generateConfig.ts"],
- "ignore": ["extensions", "extensionsLib"]
-}
diff --git a/ft_build/extensionsLib/algoliaIndex.ts b/ft_build/extensionsLib/algoliaIndex.ts
deleted file mode 100644
index e1ef87bae..000000000
--- a/ft_build/extensionsLib/algoliaIndex.ts
+++ /dev/null
@@ -1,109 +0,0 @@
-export const dependencies = {
- algoliasearch: "^4.8.3",
-};
-
-const get = (obj, path, defaultValue = undefined) => {
- const travel = (regexp) =>
- String.prototype.split
- .call(path, regexp)
- .filter(Boolean)
- .reduce(
- (res, key) => (res !== null && res !== undefined ? res[key] : res),
- obj
- );
- const result = travel(/[,[\]]+?/) || travel(/[,[\].]+?/);
- return result === undefined || result === obj ? defaultValue : result;
-};
-
-const filterSnapshot = (
- field: { docPath: string; snapshot: any },
- preservedKeys: string[]
-) => {
- return {
- docPath: field.docPath,
- ...preservedKeys.reduce((acc: any, currentKey: string) => {
- const value = get(field.snapshot, currentKey);
- if (value) {
- return { ...acc, snapshot: { [currentKey]: value, ...acc.snapshot } };
- } else return acc;
- }, {}),
- };
-};
-
-// returns object of fieldsToSync
-const rowReducer = (fieldsToSync, row) =>
- fieldsToSync.reduce(
- (
- acc: any,
- curr: string | { fieldName: string; snapshotFields: string[] }
- ) => {
- if (typeof curr === "string") {
- if (row[curr] && typeof row[curr].toDate === "function") {
- return {
- ...acc,
- [curr]: row[curr].toDate().getTime() / 1000,
- };
- } else if (row[curr] !== undefined || row[curr] !== null) {
- return { ...acc, [curr]: row[curr] };
- } else {
- return acc;
- }
- } else {
- if (row[curr.fieldName] && curr.snapshotFields) {
- return {
- ...acc,
- [curr.fieldName]: row[curr.fieldName].map((snapshot) =>
- filterSnapshot(snapshot, curr.snapshotFields)
- ),
- };
- } else {
- return acc;
- }
- }
- },
- {}
- );
-
-const significantDifference = (fieldsToSync, change) => {
- const beforeData = change.before.data();
- const afterData = change.after.data();
- return fieldsToSync.reduce((acc, field) => {
- const key = typeof field === "string" ? field : field.fieldName;
- if (JSON.stringify(beforeData[key]) !== JSON.stringify(afterData[key]))
- return true;
- else return acc;
- }, false);
-};
-
-const algoliaIndex = async (data, extensionContext) => {
- const { row, objectID, index, fieldsToSync } = data;
-
- const { triggerType, change } = extensionContext;
- const record = rowReducer(fieldsToSync, row);
- const algoliasearch = require("algoliasearch");
- const { getSecret } = require("../utils");
- const { appId, adminKey } = await getSecret("algolia");
- console.log(`algolia app id : ${appId}`);
- const client = algoliasearch(appId, adminKey);
- const _index = client.initIndex(index); // initialize algolia index
-
- switch (triggerType) {
- case "delete":
- await _index.deleteObject(objectID);
- break;
- case "update":
- if (
- significantDifference([...fieldsToSync, "_ft_forcedUpdateAt"], change)
- ) {
- _index.saveObject({ ...record, objectID });
- }
- break;
- case "create":
- await _index.saveObject({ ...record, objectID });
- break;
- default:
- break;
- }
- return true;
-};
-export default algoliaIndex;
diff --git a/ft_build/extensionsLib/apiCall.ts b/ft_build/extensionsLib/apiCall.ts
deleted file mode 100644
index 6b9db9d85..000000000
--- a/ft_build/extensionsLib/apiCall.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-export const dependencies = {
- "node-fetch": "2.6.1",
-};
-const api = async (args) => {
- const { body, url, method, callback } = args;
- const fetch = require("node-fetch");
- return fetch(url, { method: method, body: body })
- .then((res) => res.json())
- .then((json) => callback(json));
-};
-export default api;
diff --git a/ft_build/extensionsLib/bigqueryIndex.ts b/ft_build/extensionsLib/bigqueryIndex.ts
deleted file mode 100644
index 62828747d..000000000
--- a/ft_build/extensionsLib/bigqueryIndex.ts
+++ /dev/null
@@ -1,424 +0,0 @@
-export const dependencies = {
- "@google-cloud/bigquery": "^5.5.0",
-};
-
-const get = (obj, path, defaultValue = undefined) => {
- const travel = (regexp) =>
- String.prototype.split
- .call(path, regexp)
- .filter(Boolean)
- .reduce(
- (res, key) => (res !== null && res !== undefined ? res[key] : res),
- obj
- );
- const result = travel(/[,[\]]+?/) || travel(/[,[\].]+?/);
- return result === undefined || result === obj ? defaultValue : result;
-};
-
-const filterSnapshot = (
- field: { docPath: string; snapshot: any },
- preservedKeys: string[]
-) => {
- return {
- docPath: field.docPath,
- ...preservedKeys.reduce((acc: any, currentKey: string) => {
- const value = get(field.snapshot, currentKey);
- if (value) {
- return { ...acc, snapshot: { [currentKey]: value, ...acc.snapshot } };
- } else return acc;
- }, {}),
- };
-};
-
-// returns object of fieldsToSync
-const rowReducer = (fieldsToSync, row) =>
- fieldsToSync.reduce(
- (
- acc: any,
- curr: string | { fieldName: string; snapshotFields: string[] }
- ) => {
- if (typeof curr === "string") {
- if (row[curr] && typeof row[curr].toDate === "function") {
- return {
- ...acc,
- [curr]: row[curr].toDate().getTime() / 1000,
- };
- } else if (row[curr] !== undefined || row[curr] !== null) {
- return { ...acc, [curr]: row[curr] };
- } else {
- return acc;
- }
- } else {
- if (row[curr.fieldName] && curr.snapshotFields) {
- return {
- ...acc,
- [curr.fieldName]: row[curr.fieldName].map((snapshot) =>
- filterSnapshot(snapshot, curr.snapshotFields)
- ),
- };
- } else {
- return acc;
- }
- }
- },
- {}
- );
-
-const significantDifference = (fieldsToSync, change) => {
- const beforeData = change.before.data();
- const afterData = change.after.data();
- return fieldsToSync.reduce((acc, field) => {
- const key = typeof field === "string" ? field : field.fieldName;
- if (JSON.stringify(beforeData[key]) !== JSON.stringify(afterData[key]))
- return true;
- else return acc;
- }, false);
-};
-
-const transformToSQLData = (value: any, ftType: string) => {
- if (value === null || value === undefined) {
- return {
- value: `null`,
- type: "STRING",
- };
- }
-
- const sanitise = (x: string) =>
- x?.replace?.(/\"/g, '\\"')?.replace?.(/\n/g, "\\n") ?? "";
-
- switch (ftType) {
- case "SIMPLE_TEXT":
- case "LONG_TEXT":
- case "EMAIL":
- case "PHONE_NUMBER":
- case "CODE":
- case "RICH_TEXT":
- case "ID":
- case "SINGLE_SELECT":
- case "URL":
- return {
- value: `"${sanitise(value)}"`,
- type: "STRING",
- };
- case "JSON": // JSON
- case "FILE": // JSON
- case "IMAGE": // JSON
- case "USER": // JSON
- case "COLOR": // JSON
- case "DOCUMENT_SELECT":
- case "SERVICE_SELECT":
- case "ACTION":
- case "AGGREGATE":
- case "MULTI_SELECT": // array
- return {
- value: `"${sanitise(JSON.stringify(value))}"`,
- type: "STRING",
- };
- case "CHECK_BOX":
- return {
- value: value ? `true` : `false`,
- type: "BOOLEAN",
- };
- case "NUMBER":
- case "PERCENTAGE":
- case "RATING":
- case "SLIDER":
- return {
- value: Number(value),
- type: "NUMERIC",
- };
- case "DATE":
- case "DATE_TIME":
- case "DURATION":
- if (!value?.toDate) {
- return {
- value: `null`,
- type: "TIMESTAMP",
- };
- }
- return {
- value: `timestamp("${value?.toDate?.()}")`,
- type: "TIMESTAMP",
- };
- case "LAST":
- case "STATUS":
- case "SUB_TABLE":
- default:
- // unknown or meaningless to sync
- return {
- value: `null`,
- type: "STRING",
- };
- }
-};
-
-const transformToSQLValue = (ftValue: any, ftType: string) => {
- const { value } = transformToSQLData(ftValue, ftType);
- return value;
-};
-
-const transformToSQLType = (ftType: string) => {
- const { type } = transformToSQLData("", ftType);
- return type;
-};
-
-const bigqueryIndex = async (payload, extensionContext) => {
- const { objectID, index, fieldsToSync, projectID, datasetLocation } = payload;
-
- const { triggerType, change, fieldTypes } = extensionContext;
- const record = rowReducer(fieldsToSync, extensionContext.row);
- const { BigQuery } = require("@google-cloud/bigquery");
-
- const bigquery = new BigQuery();
- const _projectID = projectID ?? process.env.GCLOUD_PROJECT;
- const tableFullName = `${_projectID}.firetable.${index}`;
- console.log(
- `projectID: ${_projectID}, index: ${index}, tableFullName: ${tableFullName}`
- );
-
- // create dataset with exact name "firetable" if not exists
- async function preprocessDataset() {
- const dataset = bigquery.dataset("firetable", {
- location: datasetLocation ?? "US",
- });
- const res = await dataset.exists();
- const exists = res[0];
- if (!exists) {
- console.log("Dataset 'firetable' does not exist, creating dataset...");
- await dataset.create();
- console.log("Dataset 'firetable' created.");
- } else {
- console.log("Dataset 'firetable' exists.");
- }
- }
-
- async function preprocessTable() {
- const dataset = bigquery.dataset("firetable");
- const table = dataset.table(index);
- const res = await table.exists();
- const exists = res[0];
- if (!exists) {
- console.log(
- `Table '${index}' does not exist in dataset 'firetable', creating dataset...`
- );
- await table.create();
- console.log(`Table '${index}' created in dataset 'firetable'.`);
- } else {
- console.log(`Table ${index} exists in 'firetable'.`);
- }
- }
-
- async function preprocessSchema() {
- const dataset = bigquery.dataset("firetable");
- const table = dataset.table(index);
- const generatedTypes = Object.keys(fieldTypes)
- .filter((field) => fieldsToSync.includes(field))
- .reduce((acc, cur) => {
- return {
- [cur]: transformToSQLType(fieldTypes[cur]),
- ...acc,
- };
- }, {});
-
- const generatedSchema = [
- { name: "objectID", type: "STRING", mode: "REQUIRED" },
- ...Object.keys(generatedTypes).map((key) => {
- return {
- name: key,
- type: generatedTypes[key],
- mode: "NULLABLE",
- };
- }),
- ];
-
- const pushSchema = async () => {
- console.log("pushing schema:", generatedSchema);
- const metadata = {
- schema: generatedSchema,
- };
- await table.setMetadata(metadata);
- console.log("schema pushed.");
- };
-
- const existingRes = await table.getMetadata();
- const existingSchema = existingRes[0].schema?.fields;
-
- if (!existingSchema) {
- console.log("Existing schema does not exist, pushing schema...");
- await pushSchema();
- return;
- }
-
- // check if schema update is needed
- const objectIDFilter = (field) => field.name !== "objectID";
- const schemaIdentical =
- Object.keys(generatedTypes).length ===
- existingSchema.filter(objectIDFilter).length &&
- existingSchema
- .filter(objectIDFilter)
- .every((field) => generatedTypes[field.name] === field.type);
-
- if (schemaIdentical) {
- // no change to schema
- console.log("Existing schema detected, no update needeed.");
- return;
- }
-
- // check schema compatibility (only new field is accpted)
- const compatible =
- Object.keys(generatedTypes).length >
- existingSchema.filter(objectIDFilter).length &&
- existingSchema
- .filter(objectIDFilter)
- .filter((field) => Object.keys(generatedTypes).includes(field.name))
- .every((field) => generatedTypes[field.name] === field.type);
- if (!compatible) {
- const errorMessage =
- "New update to field types is not compatible with existing schema. Please manually remove the current bigquery table or update extension index";
- console.log(errorMessage);
- throw errorMessage;
- } else {
- console.log(
- "New field types detected and it is compatible with current schema."
- );
- }
-
- // push schema
- await pushSchema();
- }
-
- // return if the objectID exists in bool
- async function exist() {
- const query = `SELECT objectID FROM ${tableFullName}
- WHERE objectID="${objectID}"
- ;`;
- console.log(query);
- const res = await bigquery.query(query);
- const rows = res?.[0];
- return !!rows?.length;
- }
-
- function getTypeKnownRecord(data) {
- const knownTypes = Object.keys(fieldTypes);
- const givenKeys = Object.keys(data);
- const knownKeys = givenKeys.filter((key) => knownTypes.includes(key));
- const unknownKeys = givenKeys.filter((key) => !knownTypes.includes(key));
- const knownRecord = Object.keys(data)
- .filter((key) => knownKeys.includes(key))
- .reduce((obj, key) => {
- return {
- ...obj,
- [key]: data[key],
- };
- }, {});
-
- if (unknownKeys?.length > 0) {
- console.log(
- "The following fields do not exist in Firetable and are ignored.",
- unknownKeys
- );
- }
-
- return knownRecord;
- }
-
- async function insert(data) {
- const keys = Object.keys(data).join(",");
- const values = Object.keys(data)
- .map((key) => transformToSQLValue(data[key], fieldTypes[key]))
- .join(",");
- const query = `INSERT INTO ${tableFullName}
- (objectID, ${keys})
- VALUES ("${objectID}", ${values})
- ;`;
- console.log(query);
- await executeQuery(query);
- }
-
- // execute a query, if rate limited, sleep and try again until success
- // ATTENTION: cloud function might timeout the function execution time at 60,000ms
- const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
- async function executeQuery(query, delayDepth = 1) {
- try {
- const res = await bigquery.query(query);
- console.log(res);
- } catch (error) {
- if (
- error?.errors?.length === 1 &&
- (error?.errors?.[0]?.reason === "rateLimitExceeded" ||
- error?.errors?.[0]?.reason === "quotaExceeded")
- ) {
- const delay = Math.round(
- Math.floor(Math.random() * 3_000 * (delayDepth % 20) + 1000)
- );
- console.log(`API rate limited, try again in ${delay}ms`);
- await sleep(delay);
- await executeQuery(query, delayDepth + 1);
- } else {
- console.log(error?.errors ?? error);
- }
- }
- if (delayDepth === 1) {
- console.log("Query finished.");
- }
- }
-
- async function update(data) {
- const values = Object.keys(data)
- .map((key) => `${key}=${transformToSQLValue(data[key], fieldTypes[key])}`)
- .join(",");
- const query = `UPDATE ${tableFullName}
- SET ${values}
- WHERE objectID="${objectID}"
- ;`;
- console.log(query);
- await executeQuery(query);
- }
-
- async function insertOrUpdate(data) {
- const objectExists = await exist();
- if (objectExists) {
- await update(data);
- } else {
- await insert(data);
- }
- }
-
- async function remove() {
- const query = `DELETE FROM ${tableFullName}
- WHERE objectID="${objectID}"
- ;`;
- console.log(query);
- await executeQuery(query);
- }
-
- // preprocess before starting index logic
- await preprocessDataset();
- await preprocessTable();
- await preprocessSchema();
-
- // only proceed with fields that have known types
- const typeKnownRecord = getTypeKnownRecord(record);
-
- switch (triggerType) {
- case "delete":
- await remove();
- break;
- case "update":
- if (
- significantDifference([...fieldsToSync, "_ft_forcedUpdateAt"], change)
- ) {
- await insertOrUpdate(typeKnownRecord);
- } else {
- console.log("significantDifference is false, no update needed.");
- }
- break;
- case "create":
- await insertOrUpdate(typeKnownRecord);
- break;
- default:
- break;
- }
- return true;
-};
-export default bigqueryIndex;
diff --git a/ft_build/extensionsLib/docSync.ts b/ft_build/extensionsLib/docSync.ts
deleted file mode 100644
index 0e3875ceb..000000000
--- a/ft_build/extensionsLib/docSync.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-export const dependencies = {};
-
-// returns object of fieldsToSync
-const rowReducer = (fieldsToSync, row) =>
- fieldsToSync.reduce((acc: any, curr: string) => {
- if (row[curr] !== undefined && row[curr] !== null)
- return { ...acc, [curr]: row[curr] };
- else return acc;
- }, {});
-
-const significantDifference = (fieldsToSync, change) => {
- const beforeData = change.before.data();
- const afterData = change.after.data();
- return fieldsToSync.reduce((acc, field) => {
- if (JSON.stringify(beforeData[field]) !== JSON.stringify(afterData[field]))
- return true;
- else return acc;
- }, false);
-};
-
-const docSync = async (data, extensionContext) => {
- const { row, targetPath, fieldsToSync } = data;
- const { triggerType, change } = extensionContext;
- const record = rowReducer(fieldsToSync, row);
- const { db } = require("../firebaseConfig");
-
- switch (triggerType) {
- case "delete":
- try {
- await db.doc(targetPath).delete();
- } catch (error) {
- console.log(error);
- }
- break;
- case "update":
- if (
- significantDifference([...fieldsToSync, "_ft_forcedUpdateAt"], change)
- ) {
- try {
- await db.doc(targetPath).update(record);
- } catch (error) {
- console.log(error);
- }
- }
- break;
- case "create":
- await db.doc(targetPath).set(record, { merge: true });
- break;
- default:
- break;
- }
- return true;
-};
-
-export default docSync;
diff --git a/ft_build/extensionsLib/historySnapshot.ts b/ft_build/extensionsLib/historySnapshot.ts
deleted file mode 100644
index 5a9807c96..000000000
--- a/ft_build/extensionsLib/historySnapshot.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-export const dependencies = {};
-
-const significantDifference = (fieldsToSync, change) => {
- const beforeData = change.before.data();
- const afterData = change.after.data();
- return fieldsToSync.reduce((acc, field) => {
- if (JSON.stringify(beforeData[field]) !== JSON.stringify(afterData[field]))
- return true;
- else return acc;
- }, false);
-};
-
-const historySnapshot = async (data, extensionContext) => {
- const { trackedFields } = data;
- const { triggerType, change } = extensionContext;
- if (
- (triggerType === "update" &&
- significantDifference(trackedFields, change)) ||
- triggerType === "delete"
- ) {
- try {
- await change.before.ref.collection("historySnapshots").add({
- ...change.before.data(),
- archivedAt: new Date(),
- archiveEvent: triggerType,
- });
- } catch (error) {
- console.log(error);
- }
- }
- return true;
-};
-export default historySnapshot;
diff --git a/ft_build/extensionsLib/mailchimp.ts b/ft_build/extensionsLib/mailchimp.ts
deleted file mode 100644
index 5a22951b3..000000000
--- a/ft_build/extensionsLib/mailchimp.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-export const dependencies = {
- "mailchimp-api-v3": "1.15.0",
-};
-// method : 'get|post|put|patch|delete'
-// path :`/lists/${listId}/members`
-const mailchimp = async (data) => {
- const { path, method, path_params, body, query } = data;
- const mailchimpLib = require("mailchimp-api-v3");
- const utilFns = require("../utils");
- const mailchimpKey = await utilFns.getSecret("mailchimp");
- const _mailchimp = new mailchimpLib(mailchimpKey);
- return new Promise((resolve, reject) => {
- _mailchimp.request(
- {
- method,
- path,
- path_params,
- body,
- query,
- },
- resolve
- );
- });
-};
-export default mailchimp;
diff --git a/ft_build/extensionsLib/meiliIndex.ts b/ft_build/extensionsLib/meiliIndex.ts
deleted file mode 100644
index 0db3354c6..000000000
--- a/ft_build/extensionsLib/meiliIndex.ts
+++ /dev/null
@@ -1,131 +0,0 @@
-export const dependencies = {
- meilisearch: "^0.18.1",
-};
-
-const get = (obj, path, defaultValue = undefined) => {
- const travel = (regexp) =>
- String.prototype.split
- .call(path, regexp)
- .filter(Boolean)
- .reduce(
- (res, key) => (res !== null && res !== undefined ? res[key] : res),
- obj
- );
- const result = travel(/[,[\]]+?/) || travel(/[,[\].]+?/);
- return result === undefined || result === obj ? defaultValue : result;
-};
-
-const filterSnapshot = (
- field: { docPath: string; snapshot: any },
- preservedKeys: string[]
-) => {
- return {
- docPath: field.docPath,
- ...preservedKeys.reduce((acc: any, currentKey: string) => {
- const value = get(field.snapshot, currentKey);
- if (value) {
- return { ...acc, snapshot: { [currentKey]: value, ...acc.snapshot } };
- } else return acc;
- }, {}),
- };
-};
-
-// returns object of fieldsToSync
-const rowReducer = (fieldsToSync, row) =>
- fieldsToSync.reduce(
- (
- acc: any,
- curr: string | { fieldName: string; snapshotFields: string[] }
- ) => {
- if (typeof curr === "string") {
- if (row[curr] && typeof row[curr].toDate === "function") {
- return {
- ...acc,
- [curr]: row[curr].toDate().getTime() / 1000,
- };
- } else if (row[curr] !== undefined || row[curr] !== null) {
- return { ...acc, [curr]: row[curr] };
- } else {
- return acc;
- }
- } else {
- if (row[curr.fieldName] && curr.snapshotFields) {
- return {
- ...acc,
- [curr.fieldName]: row[curr.fieldName].map((snapshot) =>
- filterSnapshot(snapshot, curr.snapshotFields)
- ),
- };
- } else {
- return acc;
- }
- }
- },
- {}
- );
-
-const significantDifference = (fieldsToSync, change) => {
- const beforeData = change.before.data();
- const afterData = change.after.data();
- return fieldsToSync.reduce((acc, field) => {
- const key = typeof field === "string" ? field : field.fieldName;
- if (JSON.stringify(beforeData[key]) !== JSON.stringify(afterData[key]))
- return true;
- else return acc;
- }, false);
-};
-
-const meiliIndex = async (data, extensionContext) => {
- const { row, objectID, index, fieldsToSync } = data;
-
- const { triggerType, change } = extensionContext;
- const record = rowReducer(fieldsToSync, row);
- const { MeiliSearch } = require("meilisearch");
- const { getSecret } = require("../utils");
- const meiliConfig = await getSecret("meilisearch");
- console.log(`meilisearch host : ${meiliConfig.host}, index: ${index}`);
- const client = new MeiliSearch(meiliConfig);
- const _index = client.index(index);
-
- let res;
- switch (triggerType) {
- case "delete":
- console.log("Deleting...");
- res = await _index.deleteDocument(objectID);
- break;
- case "update":
- if (
- significantDifference([...fieldsToSync, "_ft_forcedUpdateAt"], change)
- ) {
- console.log("Updating...");
- res = await _index.updateDocuments([
- {
- id: objectID,
- ...record,
- },
- ]);
- }
- break;
- case "create":
- console.log("Creating...");
- res = await _index.addDocuments([
- {
- id: objectID,
- ...record,
- },
- ]);
- break;
- default:
- console.log("No match.");
- break;
- }
- console.log("Checking status...");
- if (res?.updateId) {
- console.log("Querying status...");
- const status = await client.index(index).getUpdateStatus(res.updateId);
- console.log("Status:", status);
- }
-
- return true;
-};
-export default meiliIndex;
diff --git a/ft_build/extensionsLib/sendgridEmail.ts b/ft_build/extensionsLib/sendgridEmail.ts
deleted file mode 100644
index 5447a374c..000000000
--- a/ft_build/extensionsLib/sendgridEmail.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-export const dependencies = {
- "@sendgrid/mail": "^7.4.2",
-};
-const sendgridEmail = async (data) => {
- const { msg } = data;
- const sgMail = require("@sendgrid/mail");
- const utilFns = require("../utils");
- sgMail.setSubstitutionWrappers("{{", "}}");
- const sendgridKey = await utilFns.getSecret("sendgrid");
- sgMail.setApiKey(sendgridKey);
- return sgMail.send(msg);
-};
-export default sendgridEmail;
diff --git a/ft_build/extensionsLib/slackMessage.ts b/ft_build/extensionsLib/slackMessage.ts
deleted file mode 100644
index 70fdca2ce..000000000
--- a/ft_build/extensionsLib/slackMessage.ts
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
-{ channels?:string[], emails?:string[], text?:string, blocks?:any,attachments?:any }
-*/
-
-export const dependencies = {
- "@slack/web-api": "^6.0.0",
-};
-
-const initSlack = async () => {
- const { getSecret } = require("../utils");
- const { token } = await getSecret("slack");
- const { WebClient } = require("@slack/web-api");
- return new WebClient(token);
-};
-
-const messageByChannel = (slackClient) => async ({
- text,
- channel,
- blocks,
- attachments,
-}: {
- channel: string;
- text: string;
- blocks: any[];
- attachments: any[];
-}) =>
- await slackClient.chat.postMessage({
- text,
- channel,
- blocks,
- attachments,
- });
-
-const messageByEmail = (slackClient) => async ({
- email,
- text,
- blocks,
- attachments,
-}: {
- email: string;
- text: string;
- blocks: any[];
- attachments: any[];
-}) => {
- try {
- const user = await slackClient.users.lookupByEmail({ email });
- if (user.ok) {
- const channel = user.user.id;
- return await messageByChannel(slackClient)({
- text,
- blocks,
- attachments,
- channel,
- });
- } else {
- return await false;
- }
- } catch (error) {
- console.log(`${error} maybe${email} is not on slack`);
- console.log(`${error}`);
- return await false;
- }
-};
-
-const slackMessage = async (data) => {
- const slackClient = await initSlack();
- const { channels, emails, text, blocks, attachments } = data;
- if (channels) {
- const messages = channels.map((channel: string) =>
- messageByChannel(slackClient)({
- text,
- blocks: blocks ?? [],
- channel,
- attachments,
- })
- );
- await Promise.all(messages);
- }
- if (emails) {
- const messages = emails.map((email: string) =>
- messageByEmail(slackClient)({
- text: text,
- blocks: blocks ?? [],
- email,
- attachments,
- })
- );
- await Promise.all(messages);
- }
- return true;
-};
-export default slackMessage;
diff --git a/ft_build/extensionsLib/task.ts b/ft_build/extensionsLib/task.ts
deleted file mode 100644
index 0dfcddf5b..000000000
--- a/ft_build/extensionsLib/task.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export const dependencies = {};
-const task = () => {
- // the code logic of task extension should be defined in extension body
- // and the return value of extension body is ignored
-};
-export default task;
diff --git a/ft_build/extensionsLib/template.ts b/ft_build/extensionsLib/template.ts
deleted file mode 100644
index 1b3e16eb1..000000000
--- a/ft_build/extensionsLib/template.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-export const dependencies = {
- // --- Add your dependencies
- // algoliasearch: "^4.8.3",
-};
-// Define your spark
-const sparkName = async (data, sparkContext) => {
- // Your spark inputs
- const { row, targetPath, fieldsToSync } = data;
- const { triggerType, change } = sparkContext;
-
- // ---------------------------------------------
- // --- Utilise your dependencies ---
- // const algoliasearch = require("algoliasearch");
-
- // ---------------------------------------------
- // --- Get the secret from Secrets Manager
- // Example: Algolia Secret
- // const { getSecret } = require("../utils");
- // const { appId, adminKey } = await getSecret("algolia");
-
- // ---------------------------------------------
- // --- Connect to any third party extensions ---
- // Example Algolia
- // const client = algoliasearch(appId, adminKey);
- // const _index = client.initIndex(index);
-
- // ---------------------------------------------
- // --- Handle required trigger actions ---
- switch (triggerType) {
- case "create":
- // create trigger actions
- break;
-
- case "update":
- // update trigger actions
- break;
-
- case "delete":
- // delete trigger actions
- break;
-
- default:
- break;
- }
- return true;
-};
-
-export default sparkName;
diff --git a/ft_build/extensionsLib/twilioMessage.ts b/ft_build/extensionsLib/twilioMessage.ts
deleted file mode 100644
index 161332588..000000000
--- a/ft_build/extensionsLib/twilioMessage.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-export const dependencies = {
- twilio: "3.56.0",
-};
-const twilioMessage = async (data) => {
- const utilFns = require("../utils");
- const { accountSid, authToken } = await utilFns.getSecret("twilio");
- const client = require("twilio")(accountSid, authToken);
- const { body, from, to } = data;
- return client.messages
- .create({ body, from, to })
- .then((message) => console.log(message.sid));
-};
-export default twilioMessage;
diff --git a/ft_build/functions/src/extensions/index.ts b/ft_build/functions/src/extensions/index.ts
deleted file mode 100644
index 0b1642b90..000000000
--- a/ft_build/functions/src/extensions/index.ts
+++ /dev/null
@@ -1,68 +0,0 @@
-import * as functions from "firebase-functions";
-import utilFns, { hasRequiredFields, getTriggerType } from "../utils";
-import { db, auth, storage } from "../firebaseConfig";
-
-const extension = (extensionConfig, fieldTypes) => async (
- change: functions.Change,
- context: functions.EventContext
-) => {
- const beforeData = change.before?.data();
- const afterData = change.after?.data();
- const ref = change.after ? change.after.ref : change.before.ref;
- const triggerType = getTriggerType(change);
- try {
- const {
- name,
- type,
- triggers,
- conditions,
- requiredFields,
- extensionBody,
- } = extensionConfig;
- const extensionContext = {
- row: triggerType === "delete" ? beforeData : afterData,
- ref,
- db,
- auth,
- change,
- triggerType,
- extensionConfig,
- utilFns,
- fieldTypes,
- storage,
- };
- if (!triggers.includes(triggerType)) return false; //check if trigger type is included in the extension
- if (
- triggerType !== "delete" &&
- requiredFields &&
- requiredFields.length !== 0 &&
- !hasRequiredFields(requiredFields, afterData)
- ) {
- console.log("requiredFields are ", requiredFields, "type is", type);
- return false; // check if it hase required fields for the extension to run
- }
- const dontRun = conditions
- ? !(typeof conditions === "function"
- ? await conditions(extensionContext)
- : conditions)
- : false; //
-
- console.log(`name: "${name}", type: "${type}", dontRun: ${dontRun}`);
-
- if (dontRun) return false;
- const extensionData = await extensionBody(extensionContext);
- console.log(`extensionData: ${JSON.stringify(extensionData)}`);
- const extensionFn = require(`./${type}`).default;
- await extensionFn(extensionData, extensionContext);
- return true;
- } catch (err) {
- const { name, type } = extensionConfig;
- console.log(
- `error in ${name} extension of type ${type}, on ${context.eventType} in Doc ${context.resource.name}`
- );
- console.error(err);
- return Promise.reject(err);
- }
-};
-
-export default extension;
diff --git a/ft_build/functions/src/index.ts b/ft_build/functions/src/index.ts
deleted file mode 100644
index 6db06ee18..000000000
--- a/ft_build/functions/src/index.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-import * as functions from "firebase-functions";
-import derivative from "./derivatives";
-import extension from "./extensions";
-import {
- functionName,
- triggerPath,
- derivativesConfig,
- documentSelectConfig,
- extensionsConfig,
- initializeConfig,
- fieldTypes,
-} from "./functionConfig";
-
-import { getTriggerType, changedDocPath } from "./utils";
-import propagate from "./propagates";
-import initialize from "./initialize";
-export const FT = {
- [functionName]: functions.firestore
- .document(triggerPath)
- .onWrite(async (change, context) => {
- const triggerType = getTriggerType(change);
- let promises: Promise[] = [];
- const extensionPromises = extensionsConfig
- .filter((extensionConfig) =>
- extensionConfig.triggers.includes(triggerType)
- )
- .map((extensionConfig) =>
- extension(extensionConfig, fieldTypes)(change, context)
- );
- console.log(
- `#${
- extensionPromises.length
- } extensions will be evaluated on ${triggerType} of ${changedDocPath(
- change
- )}`
- );
- promises = extensionPromises;
- const propagatePromise = propagate(
- change,
- documentSelectConfig,
- triggerType
- );
- promises.push(propagatePromise);
- try {
- let docUpdates = {};
- if (triggerType === "update") {
- try {
- docUpdates = await derivative(derivativesConfig)(change);
- } catch (err) {
- console.log(`caught error: ${err}`);
- }
- } else if (triggerType === "create") {
- try {
- const initialData = await initialize(initializeConfig)(
- change.after
- );
- const derivativeData = await derivative(derivativesConfig)(change);
- docUpdates = { ...initialData, ...derivativeData };
- } catch (err) {
- console.log(`caught error: ${err}`);
- }
- }
- if (Object.keys(docUpdates).length !== 0) {
- promises.push(change.after.ref.update(docUpdates));
- }
- const result = await Promise.allSettled(promises);
- console.log(JSON.stringify(result));
- } catch (err) {
- console.log(`caught error: ${err}`);
- }
- }),
-};
diff --git a/ft_build/functions/tsconfig.json b/ft_build/functions/tsconfig.json
deleted file mode 100644
index 3f1fc4014..000000000
--- a/ft_build/functions/tsconfig.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "compilerOptions": {
- "module": "commonjs",
- "noImplicitReturns": true,
- "noUnusedLocals": true,
- "outDir": "lib",
- "sourceMap": true,
- "strict": true,
- "noImplicitAny": false,
- "resolveJsonModule": true,
- "target": "es6",
- "lib": ["ESNext"],
- "strictNullChecks": false
- },
- "compileOnSave": true,
- "include": ["src", "generateConfig.ts"],
- "ignore": ["extensions"]
-}
diff --git a/ft_build/package.json b/ft_build/package.json
deleted file mode 100644
index 0f940e260..000000000
--- a/ft_build/package.json
+++ /dev/null
@@ -1,34 +0,0 @@
-{
- "name": "ft-functions-builder",
- "description": "Manages the build and deployment of Firetable cloud functions",
- "version": "1.0.0",
- "private": true,
- "main": "index.js",
- "scripts": {
- "start": "yarn build && node build",
- "build": "rm -rf build && tsc --project ./ && cp -r functions build && cp -r extensionsLib build",
- "deploy": "./deploy.sh"
- },
- "engines": {
- "node": "14"
- },
- "dependencies": {
- "body-parser": "^1.19.0",
- "cors": "^2.8.5",
- "express": "^4.17.1",
- "firebase-admin": "^9.2.0",
- "firebase-functions": "^3.11.0"
- },
- "devDependencies": {
- "@types/express": "^4.17.11",
- "@types/node": "^14.14.33",
- "firebase-tools": "^8.7.0",
- "husky": "^4.2.5",
- "js-beautify": "^1.13.0",
- "prettier": "^2.1.1",
- "pretty-quick": "^3.0.0",
- "ts-node": "^9.1.1",
- "tslint": "^6.1.0",
- "typescript": "^4.2.3"
- }
-}
diff --git a/ft_build/tsconfig.json b/ft_build/tsconfig.json
deleted file mode 100644
index c5415c671..000000000
--- a/ft_build/tsconfig.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "compilerOptions": {
- "target": "es6",
- "module": "commonjs",
- "rootDir": "./",
- "outDir": "./build",
- "esModuleInterop": true,
- "strict": true,
- "noImplicitReturns": true,
- "noUnusedLocals": false,
- "sourceMap": true,
- "noImplicitAny": false,
- "resolveJsonModule": true,
- "lib": ["ESNext"],
- "strictNullChecks": false
- },
- "compileOnSave": true,
- "exclude": ["functions", "build"],
- "include": ["*.ts", "firebase.json", "extensionsLib"]
-}
diff --git a/ft_build/utils.ts b/ft_build/utils.ts
deleted file mode 100644
index 62f3ca811..000000000
--- a/ft_build/utils.ts
+++ /dev/null
@@ -1,198 +0,0 @@
-import { db } from "./firebaseConfig";
-import admin from "firebase-admin";
-
-function firetableUser(user: admin.auth.UserRecord) {
- return {
- displayName: user?.displayName,
- email: user?.email,
- uid: user?.uid,
- emailVerified: user?.emailVerified,
- photoURL: user?.photoURL,
- timestamp: new Date(),
- };
-}
-
-async function insertErrorRecordToDB(errorRecord: object) {
- await db.collection("_FT_ERRORS").add(errorRecord);
-}
-
-async function insertErrorToStreamer(errorRecord: object, streamLogger) {
- let errorString = "";
- for (const key of [
- "command",
- "description",
- "functionConfigTs",
- "extensionsConfig",
- "stderr",
- "errorStackTrace",
- ]) {
- const value = errorRecord[key];
- if (value) {
- errorString += `\n\n${key}: ${value}`;
- }
- }
- await streamLogger.error(errorString);
-}
-
-function commandErrorHandler(
- meta: {
- user: admin.auth.UserRecord;
- description?: string;
- functionConfigTs?: string;
- extensionsConfig?: string;
- },
- streamLogger
-) {
- return async function (error, stdout, stderr) {
- await streamLogger.info(stdout);
-
- if (!error) {
- return;
- }
-
- const errorRecord = {
- errorType: "commandError",
- ranBy: firetableUser(meta.user),
- createdAt: admin.firestore.FieldValue.serverTimestamp(),
- stdout: stdout ?? "",
- stderr: stderr ?? "",
- errorStackTrace: error?.stack ?? "",
- command: error?.cmd ?? "",
- description: meta?.description ?? "",
- functionConfigTs: meta?.functionConfigTs ?? "",
- extensionsConfig: meta?.extensionsConfig ?? "",
- };
- await insertErrorToStreamer(errorRecord, streamLogger);
- insertErrorRecordToDB(errorRecord);
- };
-}
-
-async function logErrorToDB(
- data: {
- errorDescription: string;
- errorExtraInfo?: string;
- errorTraceStack?: string;
- user: admin.auth.UserRecord;
- extensionsConfig?: string;
- },
- streamLogger?
-) {
- console.error(data.errorDescription);
-
- const errorRecord = {
- errorType: "codeError",
- ranBy: firetableUser(data.user),
- description: data.errorDescription,
- createdAt: admin.firestore.FieldValue.serverTimestamp(),
- extensionsConfig: data?.extensionsConfig ?? "",
- errorExtraInfo: data?.errorExtraInfo ?? "",
- errorStackTrace: data?.errorTraceStack ?? "",
- };
- if (streamLogger) {
- await insertErrorToStreamer(errorRecord, streamLogger);
- }
- insertErrorRecordToDB(errorRecord);
-}
-
-function parseExtensionsConfig(
- extensions: string | undefined,
- user: admin.auth.UserRecord,
- streamLogger
-) {
- if (extensions) {
- try {
- // remove leading "extensions.config(" and trailing ")"
- return extensions
- .replace(/^(\s*)extensions.config\(/, "")
- .replace(/\);?\s*$/, "");
- } catch (error) {
- logErrorToDB(
- {
- errorDescription: "Extensions is not wrapped with extensions.config",
- errorTraceStack: error.stack,
- user,
- extensionsConfig: extensions,
- },
- streamLogger
- );
- }
- }
-
- return "[]";
-}
-
-async function createStreamLogger(tableConfigPath: string) {
- const startTimeStamp = Date.now();
- const fullLog: {
- log: string;
- level: "info" | "error";
- timestamp: number;
- }[] = [];
- const logRef = db
- .doc(tableConfigPath)
- .collection("ftBuildLogs")
- .doc(startTimeStamp.toString());
- await logRef.set({ startTimeStamp, status: "BUILDING" });
-
- console.log(
- `streamLogger created. tableConfigPath: ${tableConfigPath}, startTimeStamp: ${startTimeStamp}`
- );
-
- return {
- info: async (log: string) => {
- console.log(log);
- fullLog.push({
- log,
- level: "info",
- timestamp: Date.now(),
- });
- await logRef.update({
- fullLog,
- });
- },
- error: async (log: string) => {
- console.error(log);
- fullLog.push({
- log,
- level: "error",
- timestamp: Date.now(),
- });
- await logRef.update({
- fullLog,
- });
- },
- end: async () => {
- const logsDoc = await logRef.get();
- const errorLog = logsDoc
- .get("fullLog")
- .filter((log) => log.level === "error");
- if (errorLog.length !== 0) {
- console.log("streamLogger marked as FAIL");
- await logRef.update({
- status: "FAIL",
- failTimeStamp: Date.now(),
- });
- } else {
- console.log("streamLogger marked as SUCCESS");
- await logRef.update({
- status: "SUCCESS",
- successTimeStamp: Date.now(),
- });
- }
- },
- fail: async () => {
- console.log("streamLogger marked as FAIL");
- await logRef.update({
- status: "FAIL",
- failTimeStamp: Date.now(),
- });
- },
- };
-}
-
-export {
- commandErrorHandler,
- logErrorToDB,
- parseExtensionsConfig,
- createStreamLogger,
-};
diff --git a/icon.png b/icon.png
index ca0b3063e..49ae774e7 100644
Binary files a/icon.png and b/icon.png differ
diff --git a/www/package.json b/package.json
similarity index 94%
rename from www/package.json
rename to package.json
index 2c4679c66..b14b673fd 100644
--- a/www/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
{
- "name": "Firetable",
+ "name": "rowy",
"version": "2.0.0",
- "homepage": "https://firetable.io/",
+ "homepage": "https://rowy.io/",
"repository": {
"type": "git",
- "url": "https://github.com/FiretableProject/firetable.git"
+ "url": "https://github.com/rowyio/rowy.git"
},
"private": true,
"dependencies": {
@@ -72,7 +72,7 @@
"test": "craco test --env=jsdom",
"eject": "craco eject",
"env": "node createDotEnv",
- "target": "firebase target:apply hosting firetable",
+ "target": "firebase target:apply hosting rowy",
"deploy": "firebase deploy"
},
"engines": {
diff --git a/www/public/_redirects b/public/_redirects
similarity index 100%
rename from www/public/_redirects
rename to public/_redirects
diff --git a/www/public/auth.d.ts b/public/auth.d.ts
similarity index 100%
rename from www/public/auth.d.ts
rename to public/auth.d.ts
diff --git a/www/public/browserconfig.xml b/public/browserconfig.xml
similarity index 100%
rename from www/public/browserconfig.xml
rename to public/browserconfig.xml
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100644
index 000000000..812b25a92
Binary files /dev/null and b/public/favicon.ico differ
diff --git a/public/favicon/android-chrome-192x192.png b/public/favicon/android-chrome-192x192.png
new file mode 100644
index 000000000..bbe12e203
Binary files /dev/null and b/public/favicon/android-chrome-192x192.png differ
diff --git a/public/favicon/android-chrome-512x512.png b/public/favicon/android-chrome-512x512.png
new file mode 100644
index 000000000..b7c58f954
Binary files /dev/null and b/public/favicon/android-chrome-512x512.png differ
diff --git a/public/favicon/apple-touch-icon.png b/public/favicon/apple-touch-icon.png
new file mode 100644
index 000000000..00e3c18ec
Binary files /dev/null and b/public/favicon/apple-touch-icon.png differ
diff --git a/public/favicon/favicon-16x16.png b/public/favicon/favicon-16x16.png
new file mode 100644
index 000000000..59452d9e7
Binary files /dev/null and b/public/favicon/favicon-16x16.png differ
diff --git a/public/favicon/favicon-32x32.png b/public/favicon/favicon-32x32.png
new file mode 100644
index 000000000..ccb38157b
Binary files /dev/null and b/public/favicon/favicon-32x32.png differ
diff --git a/public/favicon/icon.svg b/public/favicon/icon.svg
new file mode 100755
index 000000000..cf3392630
--- /dev/null
+++ b/public/favicon/icon.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/public/favicon/mstile-144x144.png b/public/favicon/mstile-144x144.png
new file mode 100644
index 000000000..3fb388efb
Binary files /dev/null and b/public/favicon/mstile-144x144.png differ
diff --git a/public/favicon/mstile-150x150.png b/public/favicon/mstile-150x150.png
new file mode 100644
index 000000000..90c64be9d
Binary files /dev/null and b/public/favicon/mstile-150x150.png differ
diff --git a/public/favicon/mstile-310x150.png b/public/favicon/mstile-310x150.png
new file mode 100644
index 000000000..d3aaadb8e
Binary files /dev/null and b/public/favicon/mstile-310x150.png differ
diff --git a/public/favicon/mstile-310x310.png b/public/favicon/mstile-310x310.png
new file mode 100644
index 000000000..a677f33de
Binary files /dev/null and b/public/favicon/mstile-310x310.png differ
diff --git a/public/favicon/mstile-70x70.png b/public/favicon/mstile-70x70.png
new file mode 100644
index 000000000..6832520cb
Binary files /dev/null and b/public/favicon/mstile-70x70.png differ
diff --git a/public/favicon/safari-pinned-tab.svg b/public/favicon/safari-pinned-tab.svg
new file mode 100644
index 000000000..c2b3b9bca
--- /dev/null
+++ b/public/favicon/safari-pinned-tab.svg
@@ -0,0 +1,33 @@
+
+
+
+
+Created by potrace 1.14, written by Peter Selinger 2001-2017
+
+
+
+
+
diff --git a/www/public/firestore.d.ts b/public/firestore.d.ts
similarity index 100%
rename from www/public/firestore.d.ts
rename to public/firestore.d.ts
diff --git a/www/public/index.html b/public/index.html
similarity index 98%
rename from www/public/index.html
rename to public/index.html
index b11fac101..8b11e8755 100644
--- a/www/public/index.html
+++ b/public/index.html
@@ -67,7 +67,7 @@
href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&display=swap"
/>
- Firetable
+ Rowy
You need to enable JavaScript to run this app.
diff --git a/www/public/manifest.json b/public/manifest.json
similarity index 90%
rename from www/public/manifest.json
rename to public/manifest.json
index db235044f..33e568e75 100644
--- a/www/public/manifest.json
+++ b/public/manifest.json
@@ -1,6 +1,6 @@
{
- "short_name": "Firetable",
- "name": "Firetable",
+ "short_name": "Rowy",
+ "name": "Rowy",
"icons": [
{
"src": "favicon.ico",
diff --git a/www/public/robots.txt b/public/robots.txt
similarity index 100%
rename from www/public/robots.txt
rename to public/robots.txt
diff --git a/www/public/site.webmanifest b/public/site.webmanifest
similarity index 100%
rename from www/public/site.webmanifest
rename to public/site.webmanifest
diff --git a/www/public/static/tinymce_content-dark.css b/public/static/tinymce_content-dark.css
similarity index 100%
rename from www/public/static/tinymce_content-dark.css
rename to public/static/tinymce_content-dark.css
diff --git a/www/public/static/tinymce_content.css b/public/static/tinymce_content.css
similarity index 100%
rename from www/public/static/tinymce_content.css
rename to public/static/tinymce_content.css
diff --git a/www/public/storage.d.ts b/public/storage.d.ts
similarity index 99%
rename from www/public/storage.d.ts
rename to public/storage.d.ts
index 4752fb058..f1aef3f92 100644
--- a/www/public/storage.d.ts
+++ b/public/storage.d.ts
@@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/ban-types */
-// firetable/ft_build/functions/node_modules/@google-cloud/storage/build/src/bucket.d.ts
+// node_modules/@google-cloud/storage/build/src/bucket.d.ts
declare class Bucket {
/**
* The bucket's name.
diff --git a/www/src/App.test.tsx b/src/App.test.tsx
similarity index 52%
rename from www/src/App.test.tsx
rename to src/App.test.tsx
index 23c181f02..635a333f7 100644
--- a/www/src/App.test.tsx
+++ b/src/App.test.tsx
@@ -3,7 +3,7 @@ import ReactDOM from "react-dom";
import App from "./App";
it("renders without crashing", () => {
- const div = document.createElement("div");
- ReactDOM.render( , div);
- ReactDOM.unmountComponentAtNode(div);
+ const div = document.createElement("div");
+ ReactDOM.render( , div);
+ ReactDOM.unmountComponentAtNode(div);
});
diff --git a/src/App.tsx b/src/App.tsx
new file mode 100644
index 000000000..d14bd13ba
--- /dev/null
+++ b/src/App.tsx
@@ -0,0 +1,142 @@
+import { lazy, Suspense } from "react";
+import { Route, Switch, Link } from "react-router-dom";
+
+import { StyledEngineProvider } from "@material-ui/core/styles";
+import { Button } from "@material-ui/core";
+import "./space-grotesk.css";
+
+import CustomBrowserRouter from "utils/CustomBrowserRouter";
+import PrivateRoute from "utils/PrivateRoute";
+import ErrorBoundary from "components/ErrorBoundary";
+import EmptyState from "components/EmptyState";
+import Loading from "components/Loading";
+
+import { SnackProvider } from "contexts/SnackContext";
+import ConfirmationProvider from "components/ConfirmationDialog/Provider";
+import { AppProvider } from "contexts/AppContext";
+import { RowyContextProvider } from "contexts/RowyContext";
+import { SnackLogProvider } from "contexts/SnackLogContext";
+import routes from "constants/routes";
+
+import AuthView from "pages/Auth";
+import SignOutView from "pages/Auth/SignOut";
+import TestView from "pages/Test";
+import { analytics } from "analytics";
+const AuthSetupGuidePage = lazy(
+ () => import("pages/Auth/SetupGuide" /* webpackChunkName: "AuthSetupGuide" */)
+);
+
+const HomePage = lazy(
+ () => import("./pages/Home" /* webpackChunkName: "HomePage" */)
+);
+const TablePage = lazy(
+ () => import("./pages/Table" /* webpackChunkName: "TablePage" */)
+);
+const ImpersonatorAuthPage = lazy(
+ () =>
+ import(
+ "./pages/Auth/ImpersonatorAuth" /* webpackChunkName: "ImpersonatorAuthPage" */
+ )
+);
+const JwtAuthPage = lazy(
+ () => import("./pages/Auth/JwtAuth" /* webpackChunkName: "JwtAuthPage" */)
+);
+// const GridView = lazy(
+// () => import("./views/GridView" /* webpackChunkName: "GridView" */)
+// );
+
+export default function App() {
+ return (
+
+
+
+
+
+
+
+ }>
+
+ }
+ />
+ }
+ />
+ }
+ />
+ }
+ />
+ }
+ />
+ } />
+ (
+
+
+ }
+ />
+ }
+ />
+ }
+ />
+
+
+ )}
+ />
+
+ (
+
+ Go Home
+
+ }
+ fullScreen
+ />
+ )}
+ />
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/Themes.tsx b/src/Themes.tsx
new file mode 100644
index 000000000..8a8547208
--- /dev/null
+++ b/src/Themes.tsx
@@ -0,0 +1,50 @@
+import { createTheme, ThemeOptions } from "@material-ui/core/styles";
+import _merge from "lodash/merge";
+
+import { typography } from "theme/typography";
+import { colorsLight, colorsDark } from "theme/colors";
+import { components } from "theme/components";
+
+export const customizableLightTheme = (customization: ThemeOptions) => {
+ const customizedLightThemeBase = createTheme(
+ _merge(
+ {},
+ typography((customization?.typography as any) ?? {}),
+ colorsLight()
+ )
+ );
+
+ return createTheme(
+ _merge(
+ {},
+ customizedLightThemeBase,
+ components(customizedLightThemeBase),
+ customization
+ )
+ );
+};
+
+export const customizableDarkTheme = (customization: ThemeOptions) => {
+ const customizedDarkThemeBase = createTheme(
+ _merge(
+ {},
+ typography((customization?.typography as any) ?? {}),
+ colorsDark()
+ )
+ );
+
+ return createTheme(
+ _merge(
+ {},
+ customizedDarkThemeBase,
+ components(customizedDarkThemeBase),
+ customization
+ )
+ );
+};
+
+const Themes = {
+ light: customizableLightTheme,
+ dark: customizableDarkTheme,
+};
+export default Themes;
diff --git a/src/analytics.ts b/src/analytics.ts
new file mode 100644
index 000000000..8b0c855a3
--- /dev/null
+++ b/src/analytics.ts
@@ -0,0 +1,17 @@
+import firebase from "firebase/app";
+import "firebase/analytics";
+
+const firebaseConfig = {
+ apiKey: "AIzaSyArABiYGK7dZgwSk0pw_6vKbOt6U1ZRPpc",
+ authDomain: "rowy-service.firebaseapp.com",
+ projectId: "rowy-service",
+ storageBucket: "rowy-service.appspot.com",
+ messagingSenderId: "305614947641",
+ appId: "1:305614947641:web:cb10467e7c11c93d6e14e8",
+ measurementId: "G-0VWE25LFZJ",
+};
+
+// Initialize Firebase
+const rowyServiceApp = firebase.initializeApp(firebaseConfig, "rowy-service");
+
+export const analytics = firebase.analytics(rowyServiceApp);
diff --git a/src/assets/Logo.tsx b/src/assets/Logo.tsx
new file mode 100644
index 000000000..648f74be0
--- /dev/null
+++ b/src/assets/Logo.tsx
@@ -0,0 +1,27 @@
+import { useTheme } from "@material-ui/core";
+
+export default function Logo() {
+ const theme = useTheme();
+
+ return (
+
+ rowy
+
+
+
+
+ );
+}
diff --git a/www/src/assets/SpaceGrotesk-Bold.woff2 b/src/assets/SpaceGrotesk-Bold.woff2
similarity index 100%
rename from www/src/assets/SpaceGrotesk-Bold.woff2
rename to src/assets/SpaceGrotesk-Bold.woff2
diff --git a/www/src/assets/bg-pattern.svg b/src/assets/bg-pattern.svg
similarity index 100%
rename from www/src/assets/bg-pattern.svg
rename to src/assets/bg-pattern.svg
diff --git a/www/src/assets/icons/AddColumn.tsx b/src/assets/icons/AddColumn.tsx
similarity index 64%
rename from www/src/assets/icons/AddColumn.tsx
rename to src/assets/icons/AddColumn.tsx
index 92148511d..f0b50c4ec 100644
--- a/www/src/assets/icons/AddColumn.tsx
+++ b/src/assets/icons/AddColumn.tsx
@@ -2,9 +2,9 @@ import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
import { mdiTableColumnPlusAfter } from "@mdi/js";
export default function AddColumn(props: SvgIconProps) {
- return (
-
-
-
- );
+ return (
+
+
+
+ );
}
diff --git a/src/assets/icons/AddRow.tsx b/src/assets/icons/AddRow.tsx
new file mode 100644
index 000000000..e42c807b4
--- /dev/null
+++ b/src/assets/icons/AddRow.tsx
@@ -0,0 +1,9 @@
+import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
+
+export default function AddRow(props: SvgIconProps) {
+ return (
+
+
+
+ );
+}
diff --git a/www/src/assets/icons/Backburger.tsx b/src/assets/icons/Backburger.tsx
similarity index 65%
rename from www/src/assets/icons/Backburger.tsx
rename to src/assets/icons/Backburger.tsx
index 7d71de1d8..1c0d472d9 100644
--- a/www/src/assets/icons/Backburger.tsx
+++ b/src/assets/icons/Backburger.tsx
@@ -2,9 +2,9 @@ import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
import { mdiBackburger } from "@mdi/js";
export default function Backburger(props: SvgIconProps) {
- return (
-
-
-
- );
+ return (
+
+
+
+ );
}
diff --git a/www/src/assets/icons/CellResize.tsx b/src/assets/icons/CellResize.tsx
similarity index 64%
rename from www/src/assets/icons/CellResize.tsx
rename to src/assets/icons/CellResize.tsx
index f061c186d..387f17835 100644
--- a/www/src/assets/icons/CellResize.tsx
+++ b/src/assets/icons/CellResize.tsx
@@ -2,9 +2,9 @@ import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
import { mdiArrowSplitVertical } from "@mdi/js";
export default function CellResize(props: SvgIconProps) {
- return (
-
-
-
- );
+ return (
+
+
+
+ );
}
diff --git a/www/src/assets/icons/CloudLogs.tsx b/src/assets/icons/CloudLogs.tsx
similarity index 65%
rename from www/src/assets/icons/CloudLogs.tsx
rename to src/assets/icons/CloudLogs.tsx
index 75a843ef1..5bd2412db 100644
--- a/www/src/assets/icons/CloudLogs.tsx
+++ b/src/assets/icons/CloudLogs.tsx
@@ -2,9 +2,9 @@ import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
import { mdiFileTree } from "@mdi/js";
export default function CloudLogs(props: SvgIconProps) {
- return (
-
-
-
- );
+ return (
+
+
+
+ );
}
diff --git a/www/src/assets/icons/ColumnPlusAfter.tsx b/src/assets/icons/ColumnPlusAfter.tsx
similarity index 65%
rename from www/src/assets/icons/ColumnPlusAfter.tsx
rename to src/assets/icons/ColumnPlusAfter.tsx
index 6a4a22b53..7ca331161 100644
--- a/www/src/assets/icons/ColumnPlusAfter.tsx
+++ b/src/assets/icons/ColumnPlusAfter.tsx
@@ -2,9 +2,9 @@ import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
import { mdiTableColumnPlusAfter } from "@mdi/js";
export default function ColumnPlusAfter(props: SvgIconProps) {
- return (
-
-
-
- );
+ return (
+
+
+
+ );
}
diff --git a/www/src/assets/icons/ColumnPlusBefore.tsx b/src/assets/icons/ColumnPlusBefore.tsx
similarity index 65%
rename from www/src/assets/icons/ColumnPlusBefore.tsx
rename to src/assets/icons/ColumnPlusBefore.tsx
index eeea588fd..06b3f843d 100644
--- a/www/src/assets/icons/ColumnPlusBefore.tsx
+++ b/src/assets/icons/ColumnPlusBefore.tsx
@@ -2,9 +2,9 @@ import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
import { mdiTableColumnPlusBefore } from "@mdi/js";
export default function ColumnPlusBefore(props: SvgIconProps) {
- return (
-
-
-
- );
+ return (
+
+
+
+ );
}
diff --git a/www/src/assets/icons/ColumnRemove.tsx b/src/assets/icons/ColumnRemove.tsx
similarity index 64%
rename from www/src/assets/icons/ColumnRemove.tsx
rename to src/assets/icons/ColumnRemove.tsx
index 8e854e466..ccebf41f0 100644
--- a/www/src/assets/icons/ColumnRemove.tsx
+++ b/src/assets/icons/ColumnRemove.tsx
@@ -2,9 +2,9 @@ import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
import { mdiTableColumnRemove } from "@mdi/js";
export default function ColumnRemove(props: SvgIconProps) {
- return (
-
-
-
- );
+ return (
+
+
+
+ );
}
diff --git a/src/assets/icons/ConnectTable.tsx b/src/assets/icons/ConnectTable.tsx
new file mode 100644
index 000000000..968609729
--- /dev/null
+++ b/src/assets/icons/ConnectTable.tsx
@@ -0,0 +1,9 @@
+import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
+
+export default function ConnectTable(props: SvgIconProps) {
+ return (
+
+
+
+ );
+}
diff --git a/www/src/assets/icons/CopyCells.tsx b/src/assets/icons/CopyCells.tsx
similarity index 50%
rename from www/src/assets/icons/CopyCells.tsx
rename to src/assets/icons/CopyCells.tsx
index 65d4b13ad..66366c94c 100644
--- a/www/src/assets/icons/CopyCells.tsx
+++ b/src/assets/icons/CopyCells.tsx
@@ -1,9 +1,9 @@
import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
export default function CopyCells(props: SvgIconProps) {
- return (
-
-
-
- );
+ return (
+
+
+
+ );
}
diff --git a/www/src/assets/icons/Derivative.tsx b/src/assets/icons/Derivative.tsx
similarity index 64%
rename from www/src/assets/icons/Derivative.tsx
rename to src/assets/icons/Derivative.tsx
index f771a40df..6ce529959 100644
--- a/www/src/assets/icons/Derivative.tsx
+++ b/src/assets/icons/Derivative.tsx
@@ -2,9 +2,9 @@ import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
import { mdiFunctionVariant } from "@mdi/js";
export default function Derivative(props: SvgIconProps) {
- return (
-
-
-
- );
+ return (
+
+
+
+ );
}
diff --git a/src/assets/icons/Export.tsx b/src/assets/icons/Export.tsx
new file mode 100644
index 000000000..86848757f
--- /dev/null
+++ b/src/assets/icons/Export.tsx
@@ -0,0 +1,9 @@
+import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
+
+export default function Export(props: SvgIconProps) {
+ return (
+
+
+
+ );
+}
diff --git a/www/src/assets/icons/Extension.tsx b/src/assets/icons/Extension.tsx
similarity index 65%
rename from www/src/assets/icons/Extension.tsx
rename to src/assets/icons/Extension.tsx
index 6468fe71a..9cecf34fd 100644
--- a/www/src/assets/icons/Extension.tsx
+++ b/src/assets/icons/Extension.tsx
@@ -2,9 +2,9 @@ import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
import { mdiPuzzleOutline } from "@mdi/js";
export default function Extension(props: SvgIconProps) {
- return (
-
-
-
- );
+ return (
+
+
+
+ );
}
diff --git a/www/src/assets/icons/FileUpload.tsx b/src/assets/icons/FileUpload.tsx
similarity index 66%
rename from www/src/assets/icons/FileUpload.tsx
rename to src/assets/icons/FileUpload.tsx
index 7a2e21d03..799e33d7d 100644
--- a/www/src/assets/icons/FileUpload.tsx
+++ b/src/assets/icons/FileUpload.tsx
@@ -2,9 +2,9 @@ import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
import { mdiUpload } from "@mdi/js";
export default function FileUpload(props: SvgIconProps) {
- return (
-
-
-
- );
+ return (
+
+
+
+ );
}
diff --git a/src/assets/icons/Freeze.tsx b/src/assets/icons/Freeze.tsx
new file mode 100644
index 000000000..501b23f0e
--- /dev/null
+++ b/src/assets/icons/Freeze.tsx
@@ -0,0 +1,12 @@
+import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
+
+export default function FileDownload(props: SvgIconProps) {
+ return (
+
+
+
+ );
+}
diff --git a/www/src/assets/icons/Go.tsx b/src/assets/icons/Go.tsx
similarity index 74%
rename from www/src/assets/icons/Go.tsx
rename to src/assets/icons/Go.tsx
index 705609e72..1124fc3de 100644
--- a/www/src/assets/icons/Go.tsx
+++ b/src/assets/icons/Go.tsx
@@ -3,5 +3,5 @@ import { SvgIconProps } from "@material-ui/core/SvgIcon";
/** Right chevron icon with optical alignment */
export default function Go(props: SvgIconProps) {
- return ;
+ return ;
}
diff --git a/www/src/assets/icons/Id.tsx b/src/assets/icons/Id.tsx
similarity index 64%
rename from www/src/assets/icons/Id.tsx
rename to src/assets/icons/Id.tsx
index 2a7be4ef8..bfed9c3bb 100644
--- a/www/src/assets/icons/Id.tsx
+++ b/src/assets/icons/Id.tsx
@@ -2,9 +2,9 @@ import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
import { mdiIdentifier } from "@mdi/js";
export default function Id(props: SvgIconProps) {
- return (
-
-
-
- );
+ return (
+
+
+
+ );
}
diff --git a/www/src/assets/icons/Image.tsx b/src/assets/icons/Image.tsx
similarity index 64%
rename from www/src/assets/icons/Image.tsx
rename to src/assets/icons/Image.tsx
index 694078b17..c30a4ba1e 100644
--- a/www/src/assets/icons/Image.tsx
+++ b/src/assets/icons/Image.tsx
@@ -2,9 +2,9 @@ import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
import { mdiImageOutline } from "@mdi/js";
export default function Image(props: SvgIconProps) {
- return (
-
-
-
- );
+ return (
+
+
+
+ );
}
diff --git a/src/assets/icons/Import.tsx b/src/assets/icons/Import.tsx
new file mode 100644
index 000000000..fd02aad92
--- /dev/null
+++ b/src/assets/icons/Import.tsx
@@ -0,0 +1,9 @@
+import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
+
+export default function Export(props: SvgIconProps) {
+ return (
+
+
+
+ );
+}
diff --git a/www/src/assets/icons/Json.tsx b/src/assets/icons/Json.tsx
similarity index 64%
rename from www/src/assets/icons/Json.tsx
rename to src/assets/icons/Json.tsx
index a3bde93e2..9abaa29dc 100644
--- a/www/src/assets/icons/Json.tsx
+++ b/src/assets/icons/Json.tsx
@@ -2,9 +2,9 @@ import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
import { mdiCodeJson } from "@mdi/js";
export default function Json(props: SvgIconProps) {
- return (
-
-
-
- );
+ return (
+
+
+
+ );
}
diff --git a/www/src/assets/icons/MultiSelect.tsx b/src/assets/icons/MultiSelect.tsx
similarity index 64%
rename from www/src/assets/icons/MultiSelect.tsx
rename to src/assets/icons/MultiSelect.tsx
index 1564e3d9d..8d011994c 100644
--- a/www/src/assets/icons/MultiSelect.tsx
+++ b/src/assets/icons/MultiSelect.tsx
@@ -2,9 +2,9 @@ import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
import { mdiFormatListBulletedSquare } from "@mdi/js";
export default function MultiSelect(props: SvgIconProps) {
- return (
-
-
-
- );
+ return (
+
+
+
+ );
}
diff --git a/www/src/assets/icons/Number.tsx b/src/assets/icons/Number.tsx
similarity index 65%
rename from www/src/assets/icons/Number.tsx
rename to src/assets/icons/Number.tsx
index cd4e0d67b..82f0f1c13 100644
--- a/www/src/assets/icons/Number.tsx
+++ b/src/assets/icons/Number.tsx
@@ -2,9 +2,9 @@ import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
import { mdiNumeric } from "@mdi/js";
export default function Number(props: SvgIconProps) {
- return (
-
-
-
- );
+ return (
+
+
+
+ );
}
diff --git a/www/src/assets/icons/Percentage.tsx b/src/assets/icons/Percentage.tsx
similarity index 60%
rename from www/src/assets/icons/Percentage.tsx
rename to src/assets/icons/Percentage.tsx
index 413cb002f..cced468fa 100644
--- a/www/src/assets/icons/Percentage.tsx
+++ b/src/assets/icons/Percentage.tsx
@@ -2,9 +2,9 @@ import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
import { mdiPercent } from "@mdi/js";
export default function Percentage(props: SvgIconProps) {
- return (
-
-
-
- );
+ return (
+
+
+
+ );
}
diff --git a/www/src/assets/icons/RowHeight.tsx b/src/assets/icons/RowHeight.tsx
similarity index 64%
rename from www/src/assets/icons/RowHeight.tsx
rename to src/assets/icons/RowHeight.tsx
index 188bc0784..89b8fbaba 100644
--- a/www/src/assets/icons/RowHeight.tsx
+++ b/src/assets/icons/RowHeight.tsx
@@ -2,9 +2,9 @@ import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
import { mdiTableRowHeight } from "@mdi/js";
export default function RowHeight(props: SvgIconProps) {
- return (
-
-
-
- );
+ return (
+
+
+
+ );
}
diff --git a/src/assets/icons/SingleSelect.tsx b/src/assets/icons/SingleSelect.tsx
new file mode 100644
index 000000000..4506b05e7
--- /dev/null
+++ b/src/assets/icons/SingleSelect.tsx
@@ -0,0 +1,9 @@
+import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
+
+export default function SingleSelect(props: SvgIconProps) {
+ return (
+
+
+
+ );
+}
diff --git a/src/assets/icons/Slider.tsx b/src/assets/icons/Slider.tsx
new file mode 100644
index 000000000..a8768183f
--- /dev/null
+++ b/src/assets/icons/Slider.tsx
@@ -0,0 +1,9 @@
+import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
+
+export default function Slider(props: SvgIconProps) {
+ return (
+
+
+
+ );
+}
diff --git a/www/src/assets/icons/Status.tsx b/src/assets/icons/Status.tsx
similarity index 65%
rename from www/src/assets/icons/Status.tsx
rename to src/assets/icons/Status.tsx
index 1e74485bc..44b8ea768 100644
--- a/www/src/assets/icons/Status.tsx
+++ b/src/assets/icons/Status.tsx
@@ -2,9 +2,9 @@ import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
import { mdiPulse } from "@mdi/js";
export default function Status(props: SvgIconProps) {
- return (
-
-
-
- );
+ return (
+
+
+
+ );
}
diff --git a/src/assets/icons/SubTable.tsx b/src/assets/icons/SubTable.tsx
new file mode 100644
index 000000000..74783994d
--- /dev/null
+++ b/src/assets/icons/SubTable.tsx
@@ -0,0 +1,9 @@
+import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
+
+export default function SubTable(props: SvgIconProps) {
+ return (
+
+
+
+ );
+}
diff --git a/src/assets/icons/Unfreeze.tsx b/src/assets/icons/Unfreeze.tsx
new file mode 100644
index 000000000..61e3fccbe
--- /dev/null
+++ b/src/assets/icons/Unfreeze.tsx
@@ -0,0 +1,12 @@
+import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
+
+export default function FileDownload(props: SvgIconProps) {
+ return (
+
+
+
+ );
+}
diff --git a/www/src/assets/icons/Upload.tsx b/src/assets/icons/Upload.tsx
similarity index 65%
rename from www/src/assets/icons/Upload.tsx
rename to src/assets/icons/Upload.tsx
index d1f348a16..3f544aecf 100644
--- a/www/src/assets/icons/Upload.tsx
+++ b/src/assets/icons/Upload.tsx
@@ -2,9 +2,9 @@ import SvgIcon, { SvgIconProps } from "@material-ui/core/SvgIcon";
import { mdiUpload } from "@mdi/js";
export default function Upload(props: SvgIconProps) {
- return (
-
-
-
- );
+ return (
+
+
+
+ );
}
diff --git a/src/components/AppBar.tsx b/src/components/AppBar.tsx
new file mode 100644
index 000000000..7b80e0127
--- /dev/null
+++ b/src/components/AppBar.tsx
@@ -0,0 +1,76 @@
+import { Link } from "react-router-dom";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import {
+ useTheme,
+ useScrollTrigger,
+ AppBar as MuiAppBar,
+ Toolbar,
+ Grid,
+ Button,
+} from "@material-ui/core";
+
+import Logo from "assets/Logo";
+import routes from "constants/routes";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ appBar: {
+ backgroundColor: theme.palette.background.paper,
+ marginBottom: theme.spacing(6),
+ },
+
+ logo: {
+ display: "block",
+ marginRight: theme.spacing(1),
+ },
+ heading: {
+ textTransform: "none",
+ color: theme.palette.primary.main,
+ cursor: "default",
+ userSelect: "none",
+ fontFeatureSettings: '"liga"',
+ },
+
+ locationDropdown: {
+ minWidth: 140,
+ margin: 0,
+ },
+ })
+);
+
+interface IAppBarProps {}
+
+const AppBar: React.FunctionComponent = () => {
+ const classes = useStyles();
+ const theme = useTheme();
+ const trigger = useScrollTrigger({ disableHysteresis: true, threshold: 0 });
+
+ return (
+
+
+
+
+
+
+
+
+ Sign Out
+
+
+
+
+ );
+};
+
+export default AppBar;
diff --git a/src/components/Auth/AuthLayout.tsx b/src/components/Auth/AuthLayout.tsx
new file mode 100644
index 000000000..a7055ea2e
--- /dev/null
+++ b/src/components/Auth/AuthLayout.tsx
@@ -0,0 +1,95 @@
+import Div100vh from "react-div-100vh";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { Paper, Typography, LinearProgress } from "@material-ui/core";
+import { alpha } from "@material-ui/core/styles";
+
+import bgPattern from "assets/bg-pattern.svg";
+import Logo from "assets/Logo";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: {
+ backgroundBlendMode: "normal, overlay, normal, normal",
+ // backgroundImage: `
+ // linear-gradient(to bottom, rgba(255,255,255,0), #fff),
+ // linear-gradient(155deg, #303030 -4%, ${theme.palette.primary.main} 92%),
+ // url('${bgPattern}'),
+ // linear-gradient(161deg, #ecf4ff -31%, #fff4f4 160%)
+ // `,
+ backgroundImage: `
+ linear-gradient(to bottom, ${alpha(
+ theme.palette.background.default,
+ 0
+ )}, ${theme.palette.background.default} 75%),
+ linear-gradient(155deg, ${theme.palette.primary.main} 10%, ${
+ theme.palette.secondary.main
+ } 90%),
+ url('${bgPattern}'),
+ linear-gradient(161deg, ${alpha(
+ theme.palette.background.default,
+ 0.95
+ )} -31%, ${alpha(theme.palette.background.default, 0.98)} 160%)
+ `,
+
+ display: "grid",
+ placeItems: "center",
+ padding: theme.spacing(1),
+
+ cursor: "default",
+ },
+
+ paper: {
+ position: "relative",
+ overflow: "hidden",
+
+ maxWidth: 400,
+ width: "100%",
+ padding: theme.spacing(4),
+ backgroundColor: theme.palette.background.paper,
+
+ "--spacing-contents": theme.spacing(4),
+ "& > * + *": { marginTop: "var(--spacing-contents)" },
+
+ textAlign: "center",
+ },
+
+ projectName: {
+ display: "block",
+ marginTop: theme.spacing(1),
+
+ color: theme.palette.text.disabled,
+ },
+
+ progress: {
+ position: "absolute",
+ left: 0,
+ right: 0,
+ top: 0,
+ marginTop: 0,
+ },
+ })
+);
+
+export interface IAuthLayoutProps {
+ children: React.ReactNode;
+ loading?: boolean;
+}
+
+export default function AuthLayout({ children, loading }: IAuthLayoutProps) {
+ const classes = useStyles();
+
+ return (
+
+
+
+
+ {process.env.REACT_APP_FIREBASE_PROJECT_ID}
+
+ {children}
+
+ {loading && }
+
+
+ );
+}
diff --git a/src/components/Auth/FirebaseUi.tsx b/src/components/Auth/FirebaseUi.tsx
new file mode 100644
index 000000000..d531cabaf
--- /dev/null
+++ b/src/components/Auth/FirebaseUi.tsx
@@ -0,0 +1,246 @@
+import { useState, useEffect } from "react";
+import clsx from "clsx";
+
+import StyledFirebaseAuth from "react-firebaseui/StyledFirebaseAuth";
+import { Props as FirebaseUiProps } from "react-firebaseui";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { Typography } from "@material-ui/core";
+import { alpha } from "@material-ui/core/styles";
+import Skeleton from "@material-ui/core/Skeleton";
+
+import { auth, db } from "../../firebase";
+import { defaultUiConfig, getSignInOptions } from "../../firebase/firebaseui";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ "@global": {
+ ".rowy-firebaseui": {
+ "& .firebaseui-container": {
+ backgroundColor: "transparent",
+ color: theme.palette.text.primary,
+ fontFamily: theme.typography.fontFamily,
+ },
+ "& .firebaseui-text": {
+ color: theme.palette.text.secondary,
+ fontFamily: theme.typography.fontFamily,
+ },
+ "& .firebaseui-tos": {
+ ...theme.typography.caption,
+ color: theme.palette.text.disabled,
+ },
+ "& .firebaseui-country-selector": {
+ color: theme.palette.text.primary,
+ },
+ "& .firebaseui-title": {
+ ...theme.typography.h5,
+ color: theme.palette.text.primary,
+ },
+ "& .firebaseui-subtitle": {
+ ...theme.typography.h6,
+ color: theme.palette.text.secondary,
+ },
+ "& .firebaseui-error": {
+ ...theme.typography.caption,
+ color: theme.palette.error.main,
+ },
+
+ "& .firebaseui-card-content, & .firebaseui-card-footer": { padding: 0 },
+ "& .firebaseui-idp-list, & .firebaseui-tenant-list": { margin: 0 },
+ "& .firebaseui-idp-list>.firebaseui-list-item, & .firebaseui-tenant-list>.firebaseui-list-item": {
+ margin: 0,
+ },
+ "& .firebaseui-list-item + .firebaseui-list-item": {
+ paddingTop: theme.spacing(2),
+ },
+
+ "& .mdl-button": {
+ borderRadius: 24,
+ ...theme.typography.button,
+ },
+ "& .mdl-button--raised": { boxShadow: "none" },
+ "& .mdl-card": {
+ boxShadow: "none",
+ minHeight: 0,
+ },
+ "& .mdl-button--primary.mdl-button--primary": {
+ color: theme.palette.primary.main,
+ },
+ "& .mdl-button--raised.mdl-button--colored": {
+ backgroundColor: theme.palette.primary.main,
+ color: theme.palette.primary.contrastText,
+
+ "&:active, &:focus:not(:active), &:hover": {
+ backgroundColor: theme.palette.primary.main,
+ },
+ },
+
+ "& .firebaseui-idp-button, & .firebaseui-tenant-button": {
+ maxWidth: "none",
+ minHeight: 48,
+ },
+ "& .firebaseui-idp-text": {
+ ...theme.typography.button,
+
+ paddingLeft: theme.spacing(2),
+ paddingRight: Number(theme.spacing(2).replace("px", "")) + 18,
+ marginLeft: -18,
+ width: "100%",
+ textAlign: "center",
+
+ [theme.breakpoints.down("sm")]: {
+ "&.firebaseui-idp-text-long": { display: "none" },
+ "&.firebaseui-idp-text-short": { display: "table-cell" },
+ },
+ },
+
+ "& .firebaseui-idp-google": {
+ "& .firebaseui-idp-icon-wrapper::before": {
+ content: "''",
+ display: "block",
+ position: "absolute",
+ top: 2,
+ left: 2,
+ width: 48 - 4,
+ height: 48 - 4,
+ zIndex: 0,
+
+ backgroundColor: "#fff",
+ borderRadius: "50%",
+ },
+ "& .firebaseui-idp-icon-wrapper img": {
+ position: "relative",
+ left: -1,
+ },
+
+ "&>.firebaseui-idp-text": {
+ color: "#fff",
+ },
+ },
+
+ "& .firebaseui-card-header": { padding: 0 },
+ "& .firebaseui-card-actions": { padding: 0 },
+
+ "& .firebaseui-input, & .firebaseui-input-invalid": {
+ ...theme.typography.body1,
+ color: theme.palette.text.primary,
+ },
+ "& .firebaseui-textfield.mdl-textfield .firebaseui-input": {
+ borderColor: theme.palette.divider,
+ },
+ "& .mdl-textfield.is-invalid .mdl-textfield__input": {
+ borderColor: theme.palette.error.main,
+ },
+ "& .firebaseui-label": {
+ ...theme.typography.subtitle2,
+ color: theme.palette.text.secondary,
+ },
+ "& .mdl-textfield--floating-label.is-dirty .mdl-textfield__label, .mdl-textfield--floating-label.is-focused .mdl-textfield__label": {
+ color: theme.palette.text.primary,
+ },
+ "& .firebaseui-textfield.mdl-textfield .firebaseui-label:after": {
+ backgroundColor: theme.palette.primary.main,
+ },
+ "& .mdl-textfield.is-invalid .mdl-textfield__label:after": {
+ backgroundColor: theme.palette.error.main,
+ },
+
+ "& .mdl-progress>.bufferbar": {
+ background: alpha(theme.palette.primary.main, 0.33),
+ },
+ "& .mdl-progress>.progressbar": {
+ backgroundColor: theme.palette.primary.main + " !important",
+ },
+ },
+ },
+
+ signInText: {
+ display: "none",
+ [theme.breakpoints.down("sm")]: { display: "block" },
+
+ textAlign: "center",
+ color: theme.palette.text.disabled,
+ marginBottom: theme.spacing(-1),
+ },
+
+ skeleton: {
+ marginBottom: "calc(var(--spacing-contents) * -1)",
+
+ "& > *": {
+ width: "100%",
+ height: 48,
+ borderRadius: 24,
+ },
+
+ "& > * + *": {
+ marginTop: theme.spacing(2),
+ },
+ },
+ })
+);
+
+export default function FirebaseUi(props: Partial) {
+ const classes = useStyles();
+
+ const [signInOptions, setSignInOptions] = useState<
+ Parameters[0] | undefined
+ >();
+ useEffect(() => {
+ db.doc("/_rowy_/publicSettings")
+ .get()
+ .then((doc) => {
+ const options = doc?.get("signInOptions");
+ if (!options) {
+ setSignInOptions(["google"]);
+ } else {
+ setSignInOptions(options);
+ }
+ })
+ .catch(() => setSignInOptions(["google"]));
+ }, []);
+
+ if (!signInOptions)
+ return (
+
+
+
+ );
+
+ const uiConfig: firebaseui.auth.Config = {
+ ...defaultUiConfig,
+ ...props.uiConfig,
+ callbacks: {
+ uiShown: () => {
+ const node = document.getElementById("rowy-firebaseui-skeleton");
+ if (node) node.style.display = "none";
+ },
+ ...props.uiConfig?.callbacks,
+ },
+ signInOptions: getSignInOptions(signInOptions),
+ };
+
+ return (
+ <>
+
+ Sign in with
+
+
+
+ {Object.keys(signInOptions).map((_, i) => (
+
+ ))}
+
+
+
+ >
+ );
+}
diff --git a/src/components/BuilderInstaller.tsx b/src/components/BuilderInstaller.tsx
new file mode 100644
index 000000000..5781ee383
--- /dev/null
+++ b/src/components/BuilderInstaller.tsx
@@ -0,0 +1,68 @@
+import useDoc from "hooks/useDoc";
+import Modal from "components/Modal";
+import { Box, Button, CircularProgress, Typography } from "@material-ui/core";
+import { IFormDialogProps } from "./Table/ColumnMenu/NewColumn";
+import OpenInNewIcon from "@material-ui/icons/OpenInNew";
+import CheckCircleIcon from "@material-ui/icons/CheckCircle";
+
+export interface IProjectSettings
+ extends Pick {}
+
+export default function BuilderInstaller({ handleClose }: IProjectSettings) {
+ const [settingsState] = useDoc({
+ path: "_rowy_/settings",
+ });
+
+ if (settingsState.loading) return null;
+
+ const complete =
+ settingsState.doc.buildStatus === "COMPLETE" ||
+ !!settingsState.doc.buildUrl;
+ const building = settingsState.doc.buildStatus === "BUILDING";
+ const waiting = !settingsState.doc.buildStatus && !settingsState.doc.buildUrl;
+
+ return (
+
+
+ You will be redirected to Google Cloud Shell to deploy Rowy Function
+ Builder to Cloud Run.
+
+
+
+
+ {complete && (
+ <>
+
+ Deploy Complete
+ >
+ )}
+ {building && (
+ <>
+
+ Deploying...
+ >
+ )}
+ {waiting && (
+ <>
+
+
+ Waiting for deploy...
+
+ >
+ )}
+
+
+ }
+ />
+ );
+}
diff --git a/src/components/ButtonWithStatus.tsx b/src/components/ButtonWithStatus.tsx
new file mode 100644
index 000000000..eed524f43
--- /dev/null
+++ b/src/components/ButtonWithStatus.tsx
@@ -0,0 +1,65 @@
+import React from "react";
+import clsx from "clsx";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { Button, ButtonProps } from "@material-ui/core";
+import { alpha } from "@material-ui/core/styles";
+
+export const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: {
+ position: "relative",
+ zIndex: 1,
+ },
+
+ active: {
+ color:
+ theme.palette.mode === "dark"
+ ? theme.palette.primary.light
+ : theme.palette.primary.dark,
+ backgroundColor: alpha(
+ theme.palette.primary.main,
+ theme.palette.action.selectedOpacity
+ ),
+ borderColor: theme.palette.primary.main,
+
+ "&:hover": {
+ color:
+ theme.palette.mode === "dark"
+ ? theme.palette.primary.light
+ : theme.palette.primary.dark,
+ backgroundColor: alpha(
+ theme.palette.mode === "dark"
+ ? theme.palette.primary.light
+ : theme.palette.primary.dark,
+ theme.palette.action.selectedOpacity +
+ theme.palette.action.hoverOpacity
+ ),
+ borderColor: "currentColor",
+ },
+ },
+ })
+);
+
+export interface IButtonWithStatusProps extends ButtonProps {
+ active?: boolean;
+}
+
+export const ButtonWithStatus = React.forwardRef(function ButtonWithStatus_(
+ { active = false, className, ...props }: IButtonWithStatusProps,
+ ref: React.Ref
+) {
+ const classes = useStyles();
+
+ return (
+
+ );
+});
+
+export default ButtonWithStatus;
diff --git a/src/components/CodeEditor.tsx b/src/components/CodeEditor.tsx
new file mode 100644
index 000000000..4aad2cc6f
--- /dev/null
+++ b/src/components/CodeEditor.tsx
@@ -0,0 +1,114 @@
+import React, { useRef, useMemo, useState } from "react";
+import clsx from "clsx";
+import Editor, { useMonaco } from "@monaco-editor/react";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { useTheme } from "@material-ui/core";
+
+import { useRowyContext } from "contexts/RowyContext";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ editorWrapper: { position: "relative" },
+ resizeIcon: {
+ position: "absolute",
+ bottom: 0,
+ right: 0,
+ color: theme.palette.text.disabled,
+ },
+ saveButton: {
+ marginTop: theme.spacing(1),
+ },
+ })
+);
+
+export interface ICodeEditorProps {
+ onChange: (value: string) => void;
+ value: string;
+ height?: number;
+ wrapperProps?: Partial>;
+ disabled?: boolean;
+ editorOptions?: any;
+}
+
+export default function CodeEditor({
+ onChange,
+ value,
+ height = 400,
+ wrapperProps,
+ disabled,
+ editorOptions,
+}: ICodeEditorProps) {
+ const theme = useTheme();
+ const [initialEditorValue] = useState(value ?? "");
+ const { tableState } = useRowyContext();
+ const classes = useStyles();
+ const monacoInstance = useMonaco();
+
+ const editorRef = useRef();
+
+ function handleEditorDidMount(_, editor) {
+ editorRef.current = editor;
+ }
+
+ const themeTransformer = (theme: string) => {
+ switch (theme) {
+ case "dark":
+ return "vs-dark";
+ default:
+ return theme;
+ }
+ };
+
+ useMemo(async () => {
+ if (!monacoInstance) {
+ // useMonaco returns a monaco instance but initialisation is done asynchronously
+ // dont execute the logic until the instance is initialised
+ return;
+ }
+
+ try {
+ monacoInstance.languages.typescript.javascriptDefaults.setDiagnosticsOptions(
+ {
+ noSemanticValidation: true,
+ noSyntaxValidation: false,
+ }
+ );
+ // compiler options
+ monacoInstance.languages.typescript.javascriptDefaults.setCompilerOptions(
+ {
+ target: monacoInstance.languages.typescript.ScriptTarget.ES5,
+ allowNonTsExtensions: true,
+ }
+ );
+ } catch (error) {
+ console.error(
+ "An error occurred during initialization of Monaco: ",
+ error
+ );
+ }
+ }, [tableState?.columns]);
+
+ return (
+
+
+
+ );
+}
diff --git a/src/components/CodeEditorHelper/index.tsx b/src/components/CodeEditorHelper/index.tsx
new file mode 100644
index 000000000..c7e602c5c
--- /dev/null
+++ b/src/components/CodeEditorHelper/index.tsx
@@ -0,0 +1,86 @@
+import {
+ Stack,
+ Typography,
+ Grid,
+ Tooltip,
+ Chip,
+ Button,
+} from "@material-ui/core";
+import OpenIcon from "@material-ui/icons/OpenInNew";
+export interface ICodeEditorHelperProps {
+ docLink: string;
+ additionalVariables?: {
+ key: string;
+ description: string;
+ }[];
+}
+
+export default function CodeEditorHelper({
+ docLink,
+ additionalVariables,
+}: ICodeEditorHelperProps) {
+ const availableVariables = [
+ {
+ key: "row",
+ description: `row has the value of doc.data() it has type definitions using this table's schema, but you can access any field in the document.`,
+ },
+ {
+ key: "db",
+ description: `db object provides access to firestore database instance of this project. giving you access to any collection or document in this firestore instance`,
+ },
+ {
+ key: "ref",
+ description: `ref object that represents the reference to the current row in firestore db (ie: doc.ref).`,
+ },
+ {
+ key: "auth",
+ description: `auth provides access to a firebase auth instance, can be used to manage auth users or generate tokens.`,
+ },
+ {
+ key: "storage",
+ description: `firebase Storage can be accessed through this, storage.bucket() returns default storage bucket of the firebase project.`,
+ },
+ {
+ key: "utilFns",
+ description: `utilFns provides a set of functions that are commonly used, such as easy access to GCP Secret Manager`,
+ },
+ ];
+
+ return (
+
+
+ You can access:
+
+
+
+ {availableVariables.concat(additionalVariables ?? []).map((v) => (
+
+
+
+
+
+ ))}
+
+
+ }
+ target="_blank"
+ href={docLink}
+ style={{ flexShrink: 0 }}
+ >
+ Examples & Docs
+
+
+ );
+}
diff --git a/src/components/Confirmation.tsx b/src/components/Confirmation.tsx
new file mode 100644
index 000000000..bc4b5bc58
--- /dev/null
+++ b/src/components/Confirmation.tsx
@@ -0,0 +1,122 @@
+import React, { useState } from "react";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import Button from "@material-ui/core/Button";
+import Dialog from "@material-ui/core/Dialog";
+import DialogActions from "@material-ui/core/DialogActions";
+import DialogContent from "@material-ui/core/DialogContent";
+import DialogContentText from "@material-ui/core/DialogContentText";
+import DialogTitle from "@material-ui/core/DialogTitle";
+import TextField from "@material-ui/core/TextField";
+
+const useStyles = makeStyles(() =>
+ createStyles({
+ root: {
+ display: "flex",
+ flexWrap: "wrap",
+ },
+ dryWrapper: {},
+ dryField: {},
+ })
+);
+
+export interface IConfirmationProps {
+ children: JSX.Element;
+ message?: {
+ title?: string;
+ customBody?: string;
+ body?: string | React.ReactNode;
+ cancel?: string;
+ confirm?: string | JSX.Element;
+ color?: "error";
+ };
+ confirmationCommand?: string;
+ functionName?: string;
+ stopPropagation?: boolean;
+}
+
+export default function Confirmation({
+ children,
+ message,
+ confirmationCommand,
+ functionName = "onClick",
+ stopPropagation = false,
+}: IConfirmationProps) {
+ const classes = useStyles();
+ const [showDialog, setShowDialog] = useState(false);
+ const [dryText, setDryText] = useState("");
+
+ const handleClose = () => {
+ setShowDialog(false);
+ };
+
+ const confirmHandler = children.props[functionName];
+ const button = React.cloneElement(children, {
+ [functionName]: (e) => {
+ if (stopPropagation && e && e.stopPropagation) e.stopPropagation();
+ setShowDialog(true);
+ },
+ });
+
+ return (
+ <>
+ {button}
+
+
+
+ {(message && message.title) || "Are you sure?"}
+
+ {message && (
+
+ {message.customBody}
+ {message.body &&
+ (typeof message.body === "string" ? (
+ {message.body}
+ ) : (
+ message.body
+ ))}
+ {confirmationCommand && (
+
+
+ Type {confirmationCommand} below to continue:
+
+ {
+ setDryText(e.target.value);
+ }}
+ className={classes.dryField}
+ InputProps={{ disableUnderline: true }}
+ autoFocus
+ margin="dense"
+ label={confirmationCommand}
+ fullWidth
+ />
+
+ )}
+
+ )}
+
+
+ {(message && message.cancel) || "Cancel"}
+
+ {
+ confirmHandler();
+ handleClose();
+ }}
+ variant="contained"
+ color={message?.color || "primary"}
+ autoFocus
+ disabled={
+ confirmationCommand ? dryText !== confirmationCommand : false
+ }
+ >
+ {(message && message.confirm) || "Confirm"}
+
+
+
+ >
+ );
+}
diff --git a/www/src/components/ConfirmationDialog/Context.ts b/src/components/ConfirmationDialog/Context.ts
similarity index 91%
rename from www/src/components/ConfirmationDialog/Context.ts
rename to src/components/ConfirmationDialog/Context.ts
index d66daa83b..34139c12a 100644
--- a/www/src/components/ConfirmationDialog/Context.ts
+++ b/src/components/ConfirmationDialog/Context.ts
@@ -1,7 +1,7 @@
import React, { useContext } from "react";
import { IConfirmation, CONFIRMATION_EMPTY_STATE } from "./props";
const ConfirmationContext = React.createContext(
- CONFIRMATION_EMPTY_STATE
+ CONFIRMATION_EMPTY_STATE
);
export default ConfirmationContext;
diff --git a/src/components/ConfirmationDialog/Dialog.tsx b/src/components/ConfirmationDialog/Dialog.tsx
new file mode 100644
index 000000000..2c45259e6
--- /dev/null
+++ b/src/components/ConfirmationDialog/Dialog.tsx
@@ -0,0 +1,87 @@
+import { useState } from "react";
+
+import Button from "@material-ui/core/Button";
+import Dialog from "@material-ui/core/Dialog";
+import DialogActions from "@material-ui/core/DialogActions";
+import DialogContent from "@material-ui/core/DialogContent";
+import DialogContentText from "@material-ui/core/DialogContentText";
+import DialogTitle from "@material-ui/core/DialogTitle";
+import TextField from "@material-ui/core/TextField";
+import { makeStyles, createStyles } from "@material-ui/styles";
+//import {confirmationProps} from './props'
+const useStyles = makeStyles(() =>
+ createStyles({
+ root: {
+ display: "flex",
+ flexWrap: "wrap",
+ },
+ dryWrapper: {},
+ dryField: {},
+ })
+);
+
+export default function Confirmation({
+ title,
+ customBody,
+ body,
+ cancel,
+ confirm,
+ confirmationCommand,
+ handleConfirm,
+ open,
+ handleClose,
+ maxWidth = "xs",
+}: any) {
+ const classes = useStyles();
+ const [dryText, setDryText] = useState("");
+ return (
+ <>
+
+ {title ?? "Are you sure?"}
+
+
+ {customBody}
+ {body && {body} }
+ {confirmationCommand && (
+
+
+ Type {confirmationCommand} below to continue:
+
+ {
+ setDryText(e.target.value);
+ }}
+ className={classes.dryField}
+ InputProps={{ disableUnderline: true }}
+ autoFocus
+ margin="dense"
+ label={confirmationCommand}
+ fullWidth
+ />
+
+ )}
+
+
+
+ {cancel ?? "Cancel"}
+ {
+ handleConfirm();
+ handleClose();
+ }}
+ color="primary"
+ variant="contained"
+ autoFocus
+ disabled={
+ confirmationCommand ? dryText !== confirmationCommand : false
+ }
+ >
+ {confirm ?? "Confirm"}
+
+
+
+ >
+ );
+}
diff --git a/src/components/ConfirmationDialog/Provider.tsx b/src/components/ConfirmationDialog/Provider.tsx
new file mode 100644
index 000000000..eb11b0073
--- /dev/null
+++ b/src/components/ConfirmationDialog/Provider.tsx
@@ -0,0 +1,39 @@
+import React, { useState } from "react";
+
+import { confirmationProps } from "./props";
+import Dialog from "./Dialog";
+import ConfirmationContext from "./Context";
+interface IConfirmationProviderProps {
+ children: React.ReactNode;
+}
+
+const ConfirmationProvider: React.FC = ({
+ children,
+}) => {
+ const [state, setState] = useState();
+ const [open, setOpen] = useState(false);
+ const handleClose = () => {
+ setState(undefined);
+ setOpen(false);
+ };
+ const requestConfirmation = (props: confirmationProps) => {
+ setState(props);
+ setOpen(true);
+ };
+ return (
+
+ {children}
+
+
+
+ );
+};
+
+export default ConfirmationProvider;
diff --git a/www/src/components/ConfirmationDialog/index.ts b/src/components/ConfirmationDialog/index.ts
similarity index 100%
rename from www/src/components/ConfirmationDialog/index.ts
rename to src/components/ConfirmationDialog/index.ts
diff --git a/src/components/ConfirmationDialog/props.ts b/src/components/ConfirmationDialog/props.ts
new file mode 100644
index 000000000..f54b5946a
--- /dev/null
+++ b/src/components/ConfirmationDialog/props.ts
@@ -0,0 +1,24 @@
+export type confirmationProps =
+ | {
+ title?: string;
+ customBody?: string;
+ body?: string;
+ cancel?: string;
+ confirm?: string | JSX.Element;
+ confirmationCommand?: string;
+ handleConfirm: () => void;
+ open?: Boolean;
+ }
+ | undefined;
+export interface IConfirmation {
+ dialogProps?: confirmationProps;
+ handleClose: () => void;
+ open: boolean;
+ requestConfirmation: (props: confirmationProps) => void;
+}
+export const CONFIRMATION_EMPTY_STATE = {
+ dialogProps: undefined,
+ open: false,
+ handleClose: () => {},
+ requestConfirmation: () => {},
+};
diff --git a/src/components/ConnectServiceSelect/PopupContents.tsx b/src/components/ConnectServiceSelect/PopupContents.tsx
new file mode 100644
index 000000000..2d0443e59
--- /dev/null
+++ b/src/components/ConnectServiceSelect/PopupContents.tsx
@@ -0,0 +1,204 @@
+import React, { useEffect, useState } from "react";
+import clsx from "clsx";
+import { useDebouncedCallback } from "use-debounce";
+import _get from "lodash/get";
+
+import {
+ Button,
+ Checkbox,
+ Divider,
+ Grid,
+ InputAdornment,
+ List,
+ ListItemIcon,
+ ListItemText,
+ MenuItem,
+ TextField,
+ Typography,
+ Radio,
+} from "@material-ui/core";
+import SearchIcon from "@material-ui/icons/Search";
+
+import { IConnectServiceSelectProps } from ".";
+import useStyles from "./styles";
+import Loading from "components/Loading";
+
+export interface IPopupContentsProps
+ extends Omit {}
+
+// TODO: Implement infinite scroll here
+export default function PopupContents({
+ value = [],
+ onChange,
+ config,
+
+ docRef,
+}: IPopupContentsProps) {
+ const url = config.url;
+ const titleKey = config.titleKey ?? config.primaryKey;
+ const subtitleKey = config.subtitleKey;
+ const resultsKey = config.resultsKey;
+ const primaryKey = config.primaryKey;
+ const multiple = Boolean(config.multiple);
+
+ const classes = useStyles();
+
+ // Webservice search query
+ const [query, setQuery] = useState("");
+ // Webservice response
+ const [response, setResponse] = useState(null);
+
+ const [docData, setDocData] = useState(null);
+ useEffect(() => {
+ docRef.get().then((d) => setDocData(d.data()));
+ }, []);
+
+ const hits: any["hits"] = _get(response, resultsKey) ?? [];
+ const [search] = useDebouncedCallback(
+ async (query: string) => {
+ if (!docData) return;
+ if (!url) return;
+ const uri = new URL(url),
+ params = { q: query };
+ Object.keys(params).forEach((key) =>
+ uri.searchParams.append(key, params[key])
+ );
+
+ const resp = await fetch(uri.toString(), {
+ method: "POST",
+ body: JSON.stringify(docData),
+ headers: { "content-type": "application/json" },
+ });
+
+ const jsonBody = await resp.json();
+ setResponse(jsonBody);
+ },
+ 1000,
+ { leading: true }
+ );
+
+ useEffect(() => {
+ search(query);
+ }, [query, docData]);
+
+ if (!response) return ;
+
+ const select = (hit: any) => () => {
+ if (multiple) onChange([...value, hit]);
+ else onChange([hit]);
+ };
+ const deselect = (hit: any) => () => {
+ if (multiple)
+ onChange(value.filter((v) => v[primaryKey] !== hit[primaryKey]));
+ else onChange([]);
+ };
+
+ const selectedValues = value?.map((item) => _get(item, primaryKey));
+
+ const clearSelection = () => onChange([]);
+
+ return (
+
+
+ setQuery(e.target.value)}
+ fullWidth
+ variant="filled"
+ margin="dense"
+ label="Search items"
+ className={classes.noMargins}
+ InputProps={{
+ endAdornment: (
+
+
+
+ ),
+ }}
+ onClick={(e) => e.stopPropagation()}
+ onKeyDown={(e) => e.stopPropagation()}
+ />
+
+
+
+
+ {hits.map((hit) => {
+ const isSelected =
+ selectedValues.indexOf(_get(hit, primaryKey)) !== -1;
+ console.log(`Selected Values: ${selectedValues}`);
+ return (
+
+
+
+ {multiple ? (
+
+ ) : (
+
+ )}
+
+
+
+
+
+ );
+ })}
+
+
+
+ {multiple && (
+
+
+
+ {value?.length} of {hits?.length}
+
+
+
+ Clear Selection
+
+
+
+ )}
+
+ );
+}
diff --git a/src/components/ConnectServiceSelect/index.tsx b/src/components/ConnectServiceSelect/index.tsx
new file mode 100644
index 000000000..b9ee0a9b3
--- /dev/null
+++ b/src/components/ConnectServiceSelect/index.tsx
@@ -0,0 +1,73 @@
+import { lazy, Suspense } from "react";
+import clsx from "clsx";
+
+import { TextField, TextFieldProps } from "@material-ui/core";
+import useStyles from "./styles";
+import Loading from "components/Loading";
+import ErrorBoundary from "components/ErrorBoundary";
+
+const PopupContents = lazy(
+ () => import("./PopupContents" /* webpackChunkName: "PopupContents" */)
+);
+
+export type ServiceValue = { value: string; [prop: string]: any };
+
+export interface IConnectServiceSelectProps {
+ value: ServiceValue[];
+ onChange: (value: ServiceValue[]) => void;
+ row: any;
+ config: {
+ displayKey: string;
+ [key: string]: any;
+ };
+ editable?: boolean;
+ /** Optional style overrides for root MUI `TextField` component */
+ className?: string;
+ /** Override any props of the root MUI `TextField` component */
+ TextFieldProps?: Partial;
+ docRef: firebase.default.firestore.DocumentReference;
+}
+
+export default function ConnectServiceSelect({
+ value = [],
+ className,
+ TextFieldProps = {},
+ ...props
+}: IConnectServiceSelectProps) {
+ const classes = useStyles();
+
+ const sanitisedValue = Array.isArray(value) ? value : [];
+
+ return (
+ `${(value as any[]).length} selected`,
+ displayEmpty: true,
+ classes: { root: classes.selectRoot },
+ ...TextFieldProps.SelectProps,
+ // Must have this set to prevent MUI transforming `value`
+ // prop for this component to a comma-separated string
+ MenuProps: {
+ classes: { paper: classes.paper, list: classes.menuChild },
+ MenuListProps: { disablePadding: true },
+ anchorOrigin: { vertical: "bottom", horizontal: "center" },
+ transformOrigin: { vertical: "top", horizontal: "center" },
+ ...TextFieldProps.SelectProps?.MenuProps,
+ },
+ }}
+ >
+
+ }>
+
+
+
+
+ );
+}
diff --git a/src/components/ConnectServiceSelect/styles.ts b/src/components/ConnectServiceSelect/styles.ts
new file mode 100644
index 000000000..b567a3b36
--- /dev/null
+++ b/src/components/ConnectServiceSelect/styles.ts
@@ -0,0 +1,83 @@
+import { makeStyles, createStyles } from "@material-ui/styles";
+
+export const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: { minWidth: 200 },
+ selectRoot: { paddingRight: theme.spacing(4) },
+
+ paper: { overflow: "hidden", maxHeight: "calc(100% - 48px)" },
+ menuChild: {
+ padding: `0 ${theme.spacing(2)}`,
+ minWidth: 340,
+ // Need to set fixed height here so popup is positioned correctly
+ height: 340,
+ },
+
+ grid: { outline: 0 },
+
+ noMargins: { margin: 0 },
+
+ searchRow: { marginTop: theme.spacing(2) },
+
+ listRow: {
+ background: `${theme.palette.background.paper} no-repeat`,
+ position: "relative",
+ margin: theme.spacing(0, -2),
+ maxWidth: `calc(100% + ${theme.spacing(4)})`,
+
+ "&::before, &::after": {
+ content: '""',
+ position: "absolute",
+ top: 0,
+ left: 0,
+ right: 0,
+ zIndex: 9,
+
+ display: "block",
+ height: 16,
+
+ background: `linear-gradient(to bottom, #fff, rgba(255, 255, 255, 0))`,
+ },
+
+ "&::after": {
+ top: "auto",
+ bottom: 0,
+ background: `linear-gradient(to top, #fff, rgba(255, 255, 255, 0))`,
+ },
+ },
+ list: () => {
+ let maxHeightDeductions = 0;
+ maxHeightDeductions -= 64; // search box
+ maxHeightDeductions -= 48; // multiple
+ maxHeightDeductions += 8; // footer padding
+
+ return {
+ padding: theme.spacing(2, 0),
+ overflowY: "auto" as "auto",
+ // height: `calc(340px - ${-maxHeightDeductions}px)`,
+ height: 340 + maxHeightDeductions,
+ };
+ },
+
+ checkboxContainer: { minWidth: theme.spacing(36 / 8) },
+ checkbox: {
+ padding: theme.spacing(6 / 8, 9 / 8),
+ "&:hover": { background: "transparent" },
+ },
+
+ divider: { margin: theme.spacing(0, 2, 0, 6.5) },
+
+ footerRow: { marginBottom: theme.spacing(2) },
+ selectedRow: {
+ "$listRow + &": { marginTop: -theme.spacing(1) },
+ "$footerRow + &": { marginTop: -theme.spacing(2) },
+
+ marginBottom: 0,
+ "& > div": { height: 48 },
+ },
+ selectAllButton: { marginRight: -theme.spacing(1) },
+ selectedNum: { fontFeatureSettings: '"tnum"' },
+ })
+);
+
+export default useStyles;
diff --git a/src/components/EmptyState.tsx b/src/components/EmptyState.tsx
new file mode 100644
index 000000000..03e7c2d77
--- /dev/null
+++ b/src/components/EmptyState.tsx
@@ -0,0 +1,116 @@
+import clsx from "clsx";
+import Div100vh from "react-div-100vh";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import {
+ Grid,
+ GridProps,
+ Stack,
+ Typography,
+ SvgIconTypeMap,
+} from "@material-ui/core";
+import { OverridableComponent } from "@material-ui/core/OverridableComponent";
+import ErrorIcon from "@material-ui/icons/ErrorOutline";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: {
+ height: "100%",
+ width: "100%",
+ textAlign: "center",
+
+ ...theme.typography.body2,
+ },
+
+ content: {
+ "&&": { maxWidth: "25em" },
+ },
+
+ icon: {
+ color: theme.palette.action.active,
+ fontSize: "3rem",
+ },
+
+ message: {
+ marginTop: theme.spacing(1),
+ },
+
+ basicIcon: { display: "block" },
+ })
+);
+
+export interface IEmptyStateProps extends Partial {
+ /** Primary message displayed under the icon */
+ message?: React.ReactNode;
+ /** Description text displayed under primary message */
+ description?: React.ReactNode;
+ /** Override icon component */
+ Icon?: OverridableComponent;
+ /** Set height to `100vh`. Default: `false` */
+ fullScreen?: boolean;
+ /** Basic inline presentation without padding. Default: `false` */
+ basic?: boolean;
+}
+
+/**
+ * Display an empty state message with sensible defaults.
+ * By default, height is `100%`.
+ * Override with props that are passed to the root MUI `Grid` component.
+ */
+export default function EmptyState({
+ message = "Nothing Here",
+ description,
+ Icon = ErrorIcon,
+ fullScreen = false,
+ basic = false,
+ ...props
+}: IEmptyStateProps) {
+ const classes = useStyles({});
+
+ if (basic)
+ return (
+
+
+
+
+
+
+ {message}
+ {description && ": "}
+ {description}
+
+
+ );
+
+ return (
+
+
+
+
+
+ {message}
+
+
+ {description && (
+
+ {description}
+
+ )}
+
+
+ );
+}
diff --git a/src/components/ErrorBoundary.tsx b/src/components/ErrorBoundary.tsx
new file mode 100644
index 000000000..b4ca2af02
--- /dev/null
+++ b/src/components/ErrorBoundary.tsx
@@ -0,0 +1,65 @@
+import React from "react";
+import EmptyState, { IEmptyStateProps } from "./EmptyState";
+
+import { Button } from "@material-ui/core";
+import ReloadIcon from "@material-ui/icons/Refresh";
+import OpenInNewIcon from "@material-ui/icons/OpenInNew";
+import meta from "../../package.json";
+class ErrorBoundary extends React.Component {
+ state = { hasError: false, errorMessage: "" };
+
+ static getDerivedStateFromError(error: Error) {
+ // Update state so the next render will show the fallback UI.
+ return { hasError: true, errorMessage: error.message };
+ }
+
+ componentDidCatch(error: Error, errorInfo: object) {
+ console.log(error, errorInfo);
+ // You can also log the error to an error reporting service
+ //logErrorToMyService(error, errorInfo);
+ }
+
+ render() {
+ if (this.state.hasError) {
+ // You can render any custom fallback UI
+ return (
+
+ {this.state.errorMessage}
+ {this.state.errorMessage.startsWith("Loading chunk") ? (
+ }
+ onClick={() => window.location.reload()}
+ >
+ Reload
+
+ ) : (
+ }
+ >
+ Report Issue
+
+ )}
+ >
+ }
+ fullScreen
+ {...this.props}
+ />
+ );
+ }
+
+ return this.props.children;
+ }
+}
+
+export default ErrorBoundary;
diff --git a/src/components/FormattedChip.tsx b/src/components/FormattedChip.tsx
new file mode 100644
index 000000000..136955eec
--- /dev/null
+++ b/src/components/FormattedChip.tsx
@@ -0,0 +1,42 @@
+import clsx from "clsx";
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { Chip, ChipProps } from "@material-ui/core";
+
+export const VARIANTS = ["yes", "no", "maybe"];
+
+const useStyles = makeStyles(
+ createStyles({
+ yes: {
+ backgroundColor: "#58bc8a",
+ color: "hsl(150, 100%, 11%)",
+ },
+ maybe: {
+ backgroundColor: "#ffd666",
+ color: "hsl(39, 100%, 14%)",
+ },
+ no: {
+ backgroundColor: "#e67d73",
+ color: "hsl(5, 100%, 13%)",
+ },
+ })
+);
+
+// TODO: Create a more generalised solution for this
+export default function FormattedChip(props: ChipProps) {
+ const classes = useStyles();
+
+ const label =
+ typeof props.label === "string" ? props.label.toLowerCase() : "";
+
+ if (VARIANTS.includes(label)) {
+ return (
+
+ );
+ }
+
+ return ;
+}
diff --git a/src/components/Grid/AlgoliaFilters.tsx b/src/components/Grid/AlgoliaFilters.tsx
new file mode 100644
index 000000000..163256ef4
--- /dev/null
+++ b/src/components/Grid/AlgoliaFilters.tsx
@@ -0,0 +1,239 @@
+import React, { useState, useEffect } from "react";
+import { SearchIndex } from "algoliasearch/lite";
+import { FacetHit } from "@algolia/client-search";
+import useAlgolia from "use-algolia";
+import { useDebouncedCallback } from "use-debounce";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import {
+ Grid,
+ Typography,
+ Button,
+ TextField,
+ InputAdornment,
+ ListItemSecondaryAction,
+} from "@material-ui/core";
+import SearchIcon from "@material-ui/icons/Search";
+
+import MultiSelect from "@antlerengineering/multiselect";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ resetFilters: { marginRight: -theme.spacing(1) },
+
+ filterGrid: {
+ marginTop: 0,
+ marginBottom: theme.spacing(3),
+ },
+
+ listItemText: { whiteSpace: "pre-line" },
+ count: {
+ position: "static",
+ marginLeft: "auto",
+ paddingLeft: theme.spacing(1.5),
+ transform: "none",
+ color: theme.palette.text.disabled,
+ },
+ })
+);
+
+/**
+ * Generates the string to dispatch as filters for the query
+ * @param filterValues The user-selected filters
+ * @param requiredFilters Filters not selected by the user
+ */
+const generateFiltersString = (
+ filterValues: Record,
+ requiredFilters?: string
+) => {
+ if (Object.keys(filterValues).length === 0) return null;
+
+ let filtersString = Object.entries(filterValues)
+ .filter(([, values]) => values.length > 0)
+ .map(
+ ([facet, values]) =>
+ `(${values
+ .map((value) => `${facet}:"${value.replace(/"/g, '\\"')}"`)
+ .join(" OR ")})`
+ )
+ .join(" AND ");
+
+ if (requiredFilters) {
+ if (filtersString)
+ filtersString = requiredFilters + " AND " + filtersString;
+ else filtersString = requiredFilters;
+ }
+
+ return filtersString;
+};
+
+export interface IAlgoliaFiltersProps {
+ index: SearchIndex;
+ request: ReturnType[0]["request"];
+ requestDispatch: ReturnType[1];
+ requiredFilters?: string;
+ label: string;
+ filters: {
+ label: string;
+ facet: string;
+ labelTransformer?: (value: string) => string;
+ }[];
+ search?: boolean;
+}
+
+export default function AlgoliaFilters({
+ index,
+ request,
+ requestDispatch,
+ requiredFilters,
+ label,
+ filters,
+ search = true,
+}: IAlgoliaFiltersProps) {
+ const classes = useStyles();
+
+ // Store filter values
+ const [filterValues, setFilterValues] = useState>(
+ {}
+ );
+ // Push filter values to dispatch
+ useEffect(() => {
+ const filtersString = generateFiltersString(filterValues, requiredFilters);
+ if (filtersString === null) return;
+ requestDispatch({ filters: filtersString });
+ }, [filterValues]);
+
+ // Store facet values
+ const [facetValues, setFacetValues] = useState<
+ Record
+ >({});
+ // Get facet values
+ useEffect(() => {
+ if (!index) return;
+
+ filters.forEach((filter) => {
+ const params = { ...request, maxFacetHits: 100 };
+ // Ignore current user-selected value for these filters so all options
+ // continue to show up
+ params.filters =
+ generateFiltersString(
+ { ...filterValues, [filter.facet]: [] },
+ requiredFilters
+ ) ?? "";
+
+ index
+ .searchForFacetValues(filter.facet, "", params)
+ .then(({ facetHits }) =>
+ setFacetValues((other) => ({ ...other, [filter.facet]: facetHits }))
+ );
+ });
+ }, [filters, index, filterValues, requiredFilters]);
+
+ // Reset filters
+ const handleResetFilters = () => {
+ setFilterValues({});
+ setQuery("");
+ requestDispatch({ filters: requiredFilters ?? "", query: "" });
+ };
+
+ // Store search query
+ const [query, setQuery] = useState("");
+ const [handleQueryChange] = useDebouncedCallback(
+ (query: string) => requestDispatch({ query }),
+ 500
+ );
+
+ return (
+
+
+
+
+ Filter{label ? " " + label : "s"}
+
+
+
+
+
+ Reset Filters
+
+
+
+
+
+ {search && (
+
+ {
+ setQuery(e.target.value);
+ handleQueryChange(e.target.value);
+ }}
+ variant="filled"
+ type="search"
+ InputProps={{
+ startAdornment: (
+
+
+
+ ),
+ }}
+ aria-label={`Search${label ? " " + label : ""}`}
+ placeholder={`Search${label ? " " + label : ""}`}
+ hiddenLabel
+ fullWidth
+ />
+
+ )}
+
+ {filters.map((filter) => (
+
+
+ setFilterValues((other) => ({
+ ...other,
+ [filter.facet]: value,
+ }))
+ }
+ options={
+ facetValues[filter.facet]?.map((item) => ({
+ value: item.value,
+ label: filter.labelTransformer
+ ? filter.labelTransformer(item.value)
+ : item.value,
+ count: item.count,
+ })) ?? []
+ }
+ itemRenderer={(option) => (
+
+ {option.label}
+
+
+ {(option as any).count}
+
+
+
+ )}
+ searchable={facetValues[filter.facet]?.length > 10}
+ />
+
+ ))}
+
+
+ );
+}
diff --git a/src/components/Grid/Card/index.tsx b/src/components/Grid/Card/index.tsx
new file mode 100644
index 000000000..4dacf5f24
--- /dev/null
+++ b/src/components/Grid/Card/index.tsx
@@ -0,0 +1,249 @@
+import React, { useState } from "react";
+import clsx from "clsx";
+
+import {
+ Card,
+ Grid,
+ Typography,
+ Button,
+ CardActions,
+ CardContent,
+ CardMedia,
+ Divider,
+ Tabs,
+ Tab,
+} from "@material-ui/core";
+import { ButtonProps } from "@material-ui/core/Button";
+import GoIcon from "assets/icons/Go";
+
+import useStyles from "./styles";
+export interface ICardProps {
+ className?: string;
+ style?: React.CSSProperties;
+
+ overline?: React.ReactNode;
+ title?: React.ReactNode;
+ imageSource?: string;
+ imageShape?: "square" | "circle";
+ imageClassName?: string;
+
+ tabs?: {
+ label: string;
+ content: React.ReactNode;
+ disabled?: boolean;
+ }[];
+ bodyContent?: React.ReactNode;
+
+ primaryButton?: { label: string } & Partial;
+ primaryLink?: {
+ href?: string;
+ target?: string;
+ rel?: string;
+ label: string;
+ } & Partial;
+ secondaryAction?: React.ReactNode;
+}
+
+const a11yProps = (index: number) => ({
+ id: `full-width-tab-${index}`,
+ "aria-controls": `full-width-tabpanel-${index}`,
+});
+
+export default function BasicCard({
+ className,
+ style,
+
+ overline,
+ title,
+ imageSource,
+ imageShape = "square",
+ imageClassName,
+
+ tabs,
+ bodyContent,
+
+ primaryButton,
+ primaryLink,
+ secondaryAction,
+}: ICardProps) {
+ const classes = useStyles();
+
+ const [tab, setTab] = useState(0);
+
+ const handleChangeTab = (event: React.ChangeEvent<{}>, newValue: number) =>
+ setTab(newValue);
+
+ return (
+
+
+
+
+
+ {(overline || title || imageSource) && (
+
+
+
+ {overline && (
+
+ {overline}
+
+ )}
+ {title && (
+
+ {title}
+
+ )}
+
+
+ {imageSource && (
+
+
+
+ )}
+
+
+ )}
+
+ {tabs && (
+
+
+ {tabs?.map((tab, index) => (
+
+ ))}
+
+
+
+ )}
+
+ {(tabs || bodyContent) && (
+
+ {tabs && (
+
+ {tabs[tab].content && Array.isArray(tabs[tab].content) ? (
+
+ {(tabs[tab].content as React.ReactNode[]).map(
+ (element, index) => (
+
+ {element}
+
+ )
+ )}
+
+ ) : (
+ tabs[tab].content
+ )}
+
+ )}
+
+ {bodyContent && Array.isArray(bodyContent) ? (
+
+ {bodyContent.map((element, i) => (
+
+ {element}
+
+ ))}
+
+ ) : (
+ bodyContent
+ )}
+
+ )}
+
+
+
+
+ {(primaryButton || primaryLink || secondaryAction) && (
+
+
+
+
+ {primaryButton && (
+
+ ) : (
+ primaryButton.endIcon
+ )
+ }
+ >
+ {primaryButton.label}
+
+ )}
+ {primaryLink && (
+
+ ) : (
+ primaryLink.endIcon
+ )
+ }
+ >
+ {primaryLink.label}
+
+ )}
+
+ {secondaryAction && {secondaryAction} }
+
+
+ )}
+
+
+ );
+}
diff --git a/src/components/Grid/Card/styles.ts b/src/components/Grid/Card/styles.ts
new file mode 100644
index 000000000..58af8f670
--- /dev/null
+++ b/src/components/Grid/Card/styles.ts
@@ -0,0 +1,58 @@
+import { makeStyles, createStyles } from "@material-ui/styles";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: { width: "100%", height: "100%" },
+ container: { height: "100%" },
+
+ cardContentContainer: {
+ "&:last-child": { paddingBottom: theme.spacing(3) },
+ },
+ cardContent: {
+ "&:last-child": { paddingBottom: 0 },
+ },
+
+ headerContainer: {},
+ tabsContainer: { "$headerContainer + &": { marginTop: theme.spacing(2) } },
+ contentContainer: {
+ "$headerContainer + &": { marginTop: theme.spacing(2) },
+ },
+
+ overline: {
+ marginBottom: theme.spacing(3),
+ color: theme.palette.text.disabled,
+ wordBreak: "break-word",
+ },
+ title: {
+ whiteSpace: "pre-line",
+ wordBreak: "break-word",
+ },
+ image: {
+ width: 80,
+ height: 80,
+ borderRadius: theme.shape.borderRadius,
+ },
+ imageCircle: { borderRadius: "50%" },
+
+ tabs: { margin: theme.spacing(0, -2) },
+ tab: { minWidth: 0 },
+ tabDivider: { marginTop: -1 },
+
+ tabSection: { paddingTop: theme.spacing(2), height: "100%" },
+ tabContentGrid: { height: `calc(100% + ${theme.spacing(3)})` },
+
+ divider: {
+ margin: theme.spacing(2),
+ marginBottom: 0,
+ },
+ cardActions: {
+ padding: theme.spacing(0.75, 1),
+ display: "flex",
+ justifyContent: "space-between",
+ },
+
+ primaryLinkLabel: { whiteSpace: "nowrap" },
+ })
+);
+
+export default useStyles;
diff --git a/src/components/Grid/index.tsx b/src/components/Grid/index.tsx
new file mode 100644
index 000000000..42a481f26
--- /dev/null
+++ b/src/components/Grid/index.tsx
@@ -0,0 +1,81 @@
+import { Grid as MuiGrid } from "@material-ui/core";
+import Card from "./Card";
+import useAlgolia from "use-algolia";
+import AlgoliaFilters from "./AlgoliaFilters";
+import _get from "lodash/get";
+const advisorsFilters = [
+ { label: "Type", facet: "type" },
+ { label: "Experience (Industry)", facet: "expertise" },
+ { label: "Location", facet: "location" },
+];
+
+interface IGridProps {
+ collection: string;
+ filters: any[];
+}
+export const replacer = (data: any) => (m: string, key: string) => {
+ const objKey = key.split(":")[0];
+ const defaultValue = key.split(":")[1] || "";
+ return _get(data, objKey, defaultValue);
+};
+
+const CARD_CONFIG = {
+ title: `{{firstName}} {{lastName}}`,
+ image: "{{profilePhoto[0].downloadURL}}",
+ body: "{{bio}}",
+};
+export default function Grid({ collection }: IGridProps) {
+ const [algoliaState, requestDispatch, ,] = useAlgolia(
+ process.env.REACT_APP_ALGOLIA_APP_ID!,
+ process.env.REACT_APP_ALGOLIA_SEARCH_API_KEY!,
+ collection,
+ { hitsPerPage: 100 }
+ );
+
+ const isLoading = algoliaState.loading || !algoliaState.index;
+ const noResults = algoliaState.hits.length === 0;
+ const requiredFilters = ``;
+ const isEmpty =
+ noResults &&
+ algoliaState.request?.query === undefined &&
+ algoliaState.request?.filters === requiredFilters;
+ return (
+ <>
+ {algoliaState.index && !isEmpty && (
+
+ )}
+
+ {" "}
+ {algoliaState.hits.map((hit) => {
+ return (
+
+ {" "}
+ {" "}
+
+ );
+ })}
+
+ >
+ );
+}
diff --git a/src/components/HelperText.tsx b/src/components/HelperText.tsx
new file mode 100644
index 000000000..d840ffa62
--- /dev/null
+++ b/src/components/HelperText.tsx
@@ -0,0 +1,21 @@
+import { useTheme } from "@material-ui/core";
+
+export interface IHelperTextProps {
+ children: React.ReactNode;
+}
+
+export default function HelperText(props: IHelperTextProps) {
+ const theme = useTheme();
+
+ return (
+
+ );
+}
diff --git a/src/components/HomeNavigation/NavDrawer.tsx b/src/components/HomeNavigation/NavDrawer.tsx
new file mode 100644
index 000000000..c4c9ef5cd
--- /dev/null
+++ b/src/components/HomeNavigation/NavDrawer.tsx
@@ -0,0 +1,131 @@
+import { makeStyles, createStyles } from "@material-ui/styles";
+import {
+ useTheme,
+ useMediaQuery,
+ Drawer,
+ DrawerProps,
+ Grid,
+ IconButton,
+ List,
+ MenuItem,
+ ListItemIcon,
+ ListItemText,
+} from "@material-ui/core";
+import CloseIcon from "assets/icons/Backburger";
+import AddIcon from "@material-ui/icons/Add";
+
+import { APP_BAR_HEIGHT } from ".";
+import Logo from "assets/Logo";
+
+import { useRowyContext } from "contexts/RowyContext";
+import useRouter from "hooks/useRouter";
+
+export const NAV_DRAWER_WIDTH = 300;
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ paper: {
+ width: NAV_DRAWER_WIDTH,
+ overflowX: "hidden",
+ backgroundColor: theme.palette.background.paper,
+ },
+
+ logoRow: {
+ height: APP_BAR_HEIGHT,
+ marginTop: 0,
+ marginBottom: theme.spacing(1),
+
+ padding: theme.spacing(0, 2),
+ },
+ logo: { marginLeft: theme.spacing(1.5) },
+
+ nav: { height: "100%" },
+ list: {
+ display: "flex",
+ flexDirection: "column",
+ flexWrap: "nowrap",
+
+ height: "100%",
+ },
+
+ createTable: { marginTop: "auto" },
+ })
+);
+
+export interface INavDrawerProps extends DrawerProps {
+ handleCreateTable: () => void;
+}
+
+export default function NavDrawer({
+ handleCreateTable,
+ ...props
+}: INavDrawerProps) {
+ const classes = useStyles();
+ const theme = useTheme();
+ const isSm = useMediaQuery(theme.breakpoints.down("md"));
+
+ const { sections } = useRowyContext();
+ const { location } = useRouter();
+ const { hash } = location;
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {sections &&
+ Object.keys(sections).map((section) => (
+
+
+
+
+
+ ))}
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/components/HomeNavigation/index.tsx b/src/components/HomeNavigation/index.tsx
new file mode 100644
index 000000000..914b67736
--- /dev/null
+++ b/src/components/HomeNavigation/index.tsx
@@ -0,0 +1,173 @@
+import clsx from "clsx";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import {
+ useScrollTrigger,
+ Grid,
+ AppBar,
+ Toolbar,
+ IconButton,
+} from "@material-ui/core";
+import MenuIcon from "@material-ui/icons/Menu";
+
+import Logo from "assets/Logo";
+import NavDrawer, { NAV_DRAWER_WIDTH } from "./NavDrawer";
+import UserMenu from "components/Navigation/UserMenu";
+
+export const APP_BAR_HEIGHT = 56;
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ open: {},
+
+ navDrawerContainer: {
+ [theme.breakpoints.up("md")]: {
+ width: 0,
+ transition: theme.transitions.create("width", {
+ easing: theme.transitions.easing.sharp,
+ duration: theme.transitions.duration.leavingScreen,
+ }),
+
+ "$open &": {
+ width: NAV_DRAWER_WIDTH,
+ transition: theme.transitions.create("width", {
+ easing: theme.transitions.easing.easeOut,
+ duration: theme.transitions.duration.enteringScreen,
+ }),
+ },
+ },
+ },
+
+ appBar: {
+ height: APP_BAR_HEIGHT,
+
+ [theme.breakpoints.down("md")]: { paddingRight: 0 },
+
+ [theme.breakpoints.up("md")]: {
+ transition:
+ theme.transitions.create("width", {
+ easing: theme.transitions.easing.sharp,
+ duration: theme.transitions.duration.leavingScreen,
+ }) +
+ ", " +
+ theme.transitions.create(["box-shadow", "background-color"]),
+ "$open &": {
+ width: `calc(100% - ${NAV_DRAWER_WIDTH}px)`,
+ transition:
+ theme.transitions.create("width", {
+ easing: theme.transitions.easing.easeOut,
+ duration: theme.transitions.duration.enteringScreen,
+ }) +
+ ", " +
+ theme.transitions.create(["box-shadow", "background-color"]),
+ },
+ },
+
+ // Elevation 8
+ backgroundImage:
+ "linear-gradient(rgba(255, 255, 255, 0.09), rgba(255, 255, 255, 0.09))",
+ "&::before": {
+ content: "''",
+ display: "block",
+ position: "absolute",
+ top: 0,
+ right: 0,
+ bottom: 0,
+ left: 0,
+
+ backgroundColor: theme.palette.background.default,
+ transition: theme.transitions.create("opacity"),
+ },
+ },
+ appBarScrolled: {
+ "&::before": {
+ opacity: 0,
+ },
+ },
+ toolbar: {
+ height: APP_BAR_HEIGHT,
+ minHeight: "auto",
+ minWidth: 0,
+ maxWidth: "none",
+ padding: theme.spacing(0, 2),
+ },
+
+ openButton: {
+ opacity: 1,
+ transition: theme.transitions.create("opacity"),
+ "$open &": { opacity: 0 },
+ },
+ logo: {
+ flex: 1,
+ textAlign: "center",
+
+ opacity: 1,
+ transition: theme.transitions.create("opacity"),
+ "$open &": { opacity: 0 },
+ },
+ })
+);
+
+export interface IHomeNavigationProps {
+ children: React.ReactNode;
+
+ open: boolean;
+ setOpen: React.Dispatch>;
+
+ handleCreateTable: () => void;
+}
+
+export default function HomeNavigation({
+ children,
+ open,
+ setOpen,
+ handleCreateTable,
+}: IHomeNavigationProps) {
+ const classes = useStyles();
+ const trigger = useScrollTrigger({ disableHysteresis: true, threshold: 0 });
+
+ return (
+
+
+ setOpen(false)}
+ handleCreateTable={handleCreateTable}
+ />
+
+
+
+
+
+ setOpen(true)}
+ edge="start"
+ size="large"
+ className={classes.openButton}
+ >
+
+
+
+
+
+
+
+
+
+
+
+ {children}
+
+
+ );
+}
diff --git a/src/components/Loading.tsx b/src/components/Loading.tsx
new file mode 100644
index 000000000..f44f11785
--- /dev/null
+++ b/src/components/Loading.tsx
@@ -0,0 +1,47 @@
+import Div100vh from "react-div-100vh";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { Grid, CircularProgress, Typography } from "@material-ui/core";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: {
+ height: "100%",
+ width: "100%",
+ textAlign: "center",
+ },
+ progress: { color: theme.palette.action.active },
+ content: { maxWidth: "25em" },
+ message: { marginTop: theme.spacing(1) },
+ })
+);
+interface ILoading {
+ message?: string;
+ fullScreen?: boolean;
+}
+
+export default function Loading({
+ message = "Loading",
+ fullScreen = false,
+}: ILoading) {
+ const classes = useStyles({});
+
+ return (
+
+
+
+
+ {message}
+
+
+
+ );
+}
diff --git a/src/components/Modal/SlideTransition.tsx b/src/components/Modal/SlideTransition.tsx
new file mode 100644
index 000000000..fda269b28
--- /dev/null
+++ b/src/components/Modal/SlideTransition.tsx
@@ -0,0 +1,77 @@
+import React from "react";
+import { useTheme } from "@material-ui/core";
+import { Transition } from "react-transition-group";
+import { TransitionProps } from "react-transition-group/Transition";
+import { TransitionProps as MuiTransitionProps } from "@material-ui/core/transitions";
+
+export const SlideTransition: React.ForwardRefExoticComponent<
+ Pick & React.RefAttributes
+> = React.forwardRef(
+ ({ children, ...props }: TransitionProps, ref: React.Ref) => {
+ const theme = useTheme();
+
+ if (!children) return null;
+
+ const defaultStyle = {
+ opacity: 0,
+ transform: "translateY(16px)",
+
+ transition: theme.transitions.create(["transform", "opacity"], {
+ duration: "300ms",
+ easing: "cubic-bezier(0.075, 0.82, 0.165, 1)",
+ }),
+ };
+
+ const transitionStyles = {
+ entering: {
+ willChange: "transform, opacity",
+ },
+
+ entered: {
+ opacity: 1,
+ transform: "none",
+ },
+
+ exiting: {
+ opacity: 0,
+ transform: "none",
+
+ transition: theme.transitions.create(["opacity"], {
+ duration: theme.transitions.duration.leavingScreen,
+ }),
+ },
+
+ exited: {
+ opacity: 0,
+ transform: "none",
+ transition: "none",
+ },
+
+ unmounted: {},
+ };
+
+ return (
+
+ {(state) =>
+ React.cloneElement(children as any, {
+ style: { ...defaultStyle, ...transitionStyles[state] },
+ ref,
+ })
+ }
+
+ );
+ }
+);
+
+export default SlideTransition;
+
+export const SlideTransitionMui = React.forwardRef(function Transition(
+ props: MuiTransitionProps & { children?: React.ReactElement },
+ ref: React.Ref
+) {
+ return ;
+});
diff --git a/src/components/Modal/index.tsx b/src/components/Modal/index.tsx
new file mode 100644
index 000000000..c77a7c5d4
--- /dev/null
+++ b/src/components/Modal/index.tsx
@@ -0,0 +1,124 @@
+import { ReactNode, useState } from "react";
+
+import {
+ useTheme,
+ useMediaQuery,
+ Dialog,
+ DialogProps,
+ Stack,
+ DialogTitle,
+ IconButton,
+ DialogContent,
+ DialogActions,
+ Button,
+ ButtonProps,
+} from "@material-ui/core";
+import CloseIcon from "@material-ui/icons/Close";
+
+import { SlideTransitionMui } from "./SlideTransition";
+
+export interface IModalProps extends Partial> {
+ onClose: () => void;
+ disableBackdropClick?: boolean;
+
+ title: ReactNode;
+ header?: ReactNode;
+ footer?: ReactNode;
+
+ children?: ReactNode;
+ body?: ReactNode;
+
+ actions?: {
+ primary?: Partial;
+ secondary?: Partial;
+ };
+
+ hideCloseButton?: boolean;
+ fullHeight?: boolean;
+}
+
+export default function Modal({
+ onClose,
+ disableBackdropClick,
+ title,
+ header,
+ footer,
+ children,
+ body,
+ actions,
+ hideCloseButton,
+ fullHeight,
+ ...props
+}: IModalProps) {
+ const theme = useTheme();
+ const isMobile = useMediaQuery(theme.breakpoints.down("sm"));
+
+ const [open, setOpen] = useState(true);
+ const handleClose = (_, reason?: string) => {
+ if (disableBackdropClick && reason === "backdropClick") return;
+
+ setOpen(false);
+ setTimeout(() => onClose(), 300);
+ };
+
+ return (
+
+
+
+ {title}
+
+
+ {!hideCloseButton && (
+
+
+
+ )}
+
+
+ {header}
+
+ {children || body}
+
+ {footer}
+
+ {actions && (
+
+ {actions.secondary && }
+
+ {actions.primary && (
+
+ )}
+
+ )}
+
+ );
+}
diff --git a/src/components/Navigation/Breadcrumbs.tsx b/src/components/Navigation/Breadcrumbs.tsx
new file mode 100644
index 000000000..9af6cc858
--- /dev/null
+++ b/src/components/Navigation/Breadcrumbs.tsx
@@ -0,0 +1,139 @@
+import _find from "lodash/find";
+import queryString from "query-string";
+import { Link as RouterLink } from "react-router-dom";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import {
+ Breadcrumbs as MuiBreadcrumbs,
+ BreadcrumbsProps,
+ Link,
+ Typography,
+} from "@material-ui/core";
+import ArrowRightIcon from "@material-ui/icons/ChevronRight";
+
+import { useRowyContext } from "contexts/RowyContext";
+import useRouter from "hooks/useRouter";
+import routes from "constants/routes";
+import { DRAWER_COLLAPSED_WIDTH } from "components/SideDrawer";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ ol: {
+ // alignItems: "baseline",
+
+ paddingLeft: theme.spacing(2),
+ // paddingRight: DRAWER_COLLAPSED_WIDTH,
+
+ userSelect: "none",
+ },
+
+ li: {
+ // display: "flex",
+ // alignItems: "center",
+ // lineHeight: 32,
+
+ textTransform: "capitalize",
+ "&:first-of-type": { textTransform: "capitalize" },
+ },
+
+ separator: {
+ // alignSelf: "flex-end",
+ // "& svg": {
+ // position: "relative",
+ // bottom: -1.5,
+ // },
+ },
+ })
+);
+
+export default function Breadcrumbs(props: BreadcrumbsProps) {
+ const classes = useStyles();
+
+ const { tables, tableState } = useRowyContext();
+ const collection = tableState?.tablePath || "";
+
+ const router = useRouter();
+ const parentLabel = decodeURIComponent(
+ queryString.parse(router.location.search).parentLabel as string
+ );
+
+ const breadcrumbs = collection.split("/");
+
+ const section = _find(tables, ["collection", breadcrumbs[0]])?.section || "";
+ const getLabel = (collection: string) =>
+ _find(tables, ["collection", collection])?.name || collection;
+
+ return (
+ }
+ aria-label="sub-table breadcrumbs"
+ classes={classes}
+ // component="div"
+ {...(props as any)}
+ >
+ {/* Section name */}
+ {section && (
+
+ {section}
+
+ )}
+
+ {breadcrumbs.map((crumb: string, index) => {
+ // If it’s the first breadcrumb, show with specific style
+ const crumbProps = {
+ key: index,
+ variant: "h6",
+ component: index === 0 ? "h2" : "div",
+ color:
+ index === breadcrumbs.length - 1 ? "textPrimary" : "textSecondary",
+ } as const;
+
+ // If it’s the last crumb, just show the label without linking
+ if (index === breadcrumbs.length - 1)
+ return (
+
+ {getLabel(crumb) || crumb.replace(/([A-Z])/g, " $1")}
+
+ );
+
+ // If odd: breadcrumb points to a document — link to rowRef
+ // TODO: show a picker here to switch between sub tables
+ if (index % 2 === 1)
+ return (
+
+ {getLabel(
+ parentLabel.split(",")[Math.ceil(index / 2) - 1] || crumb
+ )}
+
+ );
+
+ // Otherwise, even: breadcrumb points to a Firestore collection
+ return (
+
+ {getLabel(crumb) || crumb.replace(/([A-Z])/g, " $1")}
+
+ );
+ })}
+
+ );
+}
diff --git a/src/components/Navigation/NavDrawer.tsx b/src/components/Navigation/NavDrawer.tsx
new file mode 100644
index 000000000..91e48bca0
--- /dev/null
+++ b/src/components/Navigation/NavDrawer.tsx
@@ -0,0 +1,97 @@
+import { Link } from "react-router-dom";
+
+import {
+ Drawer,
+ DrawerProps,
+ Stack,
+ IconButton,
+ List,
+ MenuItem,
+ ListItemIcon,
+ ListItemText,
+ Divider,
+} from "@material-ui/core";
+import HomeIcon from "@material-ui/icons/HomeOutlined";
+import SettingsIcon from "@material-ui/icons/SettingsOutlined";
+import CloseIcon from "assets/icons/Backburger";
+
+import { APP_BAR_HEIGHT } from ".";
+import Logo from "assets/Logo";
+import NavDrawerItem from "./NavDrawerItem";
+
+import { useRowyContext } from "contexts/RowyContext";
+import { routes } from "constants/routes";
+
+export const NAV_DRAWER_WIDTH = 256;
+
+export interface INavDrawerProps extends DrawerProps {
+ currentSection?: string;
+ currentTable: string;
+}
+
+export default function NavDrawer({
+ currentSection,
+ currentTable,
+ ...props
+}: INavDrawerProps) {
+ const { sections } = useRowyContext();
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {sections &&
+ Object.entries(sections).map(([section, tables]) => (
+
+ ))}
+
+
+
+ );
+}
diff --git a/src/components/Navigation/NavDrawerItem.tsx b/src/components/Navigation/NavDrawerItem.tsx
new file mode 100644
index 000000000..60d1de82e
--- /dev/null
+++ b/src/components/Navigation/NavDrawerItem.tsx
@@ -0,0 +1,126 @@
+import { useState } from "react";
+import { Link } from "react-router-dom";
+import clsx from "clsx";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { List, MenuItem, ListItemText, Collapse } from "@material-ui/core";
+import ArrowDropDownIcon from "@material-ui/icons/ArrowDropDown";
+
+import { Table } from "contexts/RowyContext";
+import { routes } from "constants/routes";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ listItem: {
+ width: `calc(100% - ${theme.spacing(2)})`,
+ margin: theme.spacing(0, 1),
+ padding: theme.spacing(0.75, 0.25, 0.75, 1),
+ },
+ listItemSelected: {
+ "&&, &&:hover": { backgroundColor: theme.palette.action.selected },
+ "$listItem&:before": {
+ top: (36 - 16) / 2,
+ },
+ },
+ listItemIcon: {},
+ listItemText: {
+ ...theme.typography.body2,
+ display: "block",
+ color: "inherit",
+ },
+
+ dropdownIcon: {
+ color: theme.palette.action.active,
+ transition: theme.transitions.create("transform"),
+ },
+ dropdownIconOpen: { transform: "rotate(180deg)" },
+
+ childListItem: {
+ minHeight: 36,
+ paddingLeft: theme.spacing(4),
+ },
+ childListItemText: {
+ ...theme.typography.body2,
+ display: "block",
+ color: "inherit",
+ },
+ })
+);
+
+export interface INavDrawerItemProps {
+ section: string;
+ tables: Table[];
+
+ currentSection?: string;
+ currentTable: string;
+}
+
+export default function NavDrawerItem({
+ section,
+ tables,
+ currentSection,
+ currentTable,
+}: INavDrawerItemProps) {
+ const classes = useStyles();
+
+ const [open, setOpen] = useState(section === currentSection);
+
+ return (
+
+ setOpen((o) => !o)}
+ >
+
+
+
+
+
+
+
+ {tables.map((table) => (
+
+
+
+
+
+ ))}
+
+
+
+ );
+}
diff --git a/src/components/Navigation/Notifications/index.tsx b/src/components/Navigation/Notifications/index.tsx
new file mode 100644
index 000000000..481204af4
--- /dev/null
+++ b/src/components/Navigation/Notifications/index.tsx
@@ -0,0 +1,113 @@
+import React from "react";
+import {
+ IconButton,
+ Popover,
+ List,
+ ListItemAvatar,
+ ListItem,
+ Avatar,
+ ListItemText,
+ ListItemSecondaryAction,
+ Badge,
+} from "@material-ui/core";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+
+import ErrorIcon from "@material-ui/icons/Error";
+import DeleteIcon from "@material-ui/icons/Delete";
+
+import BellIcon from "@material-ui/icons/Notifications";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ typography: {
+ padding: theme.spacing(2),
+ },
+ })
+);
+
+type Notification = {
+ title: string;
+ subtitle: string;
+ link?: string;
+ variant: "error" | "success" | "info" | "warning";
+};
+
+const Notification = () => {
+ const classes = useStyles();
+ const [anchorEl, setAnchorEl] = React.useState(
+ null
+ );
+
+ const handleClick = (event: React.MouseEvent) => {
+ setAnchorEl(event.currentTarget);
+ };
+
+ const handleClose = () => {
+ setAnchorEl(null);
+ };
+
+ const open = Boolean(anchorEl);
+ const id = open ? "simple-popover" : undefined;
+
+ const notifications: Notification[] = [
+ {
+ title: "a",
+ subtitle: "a",
+ variant: "error",
+ link:
+ "https://console.cloud.google.com/cloud-build/builds;region=global/f7b8fd9b-eb6e-401f-a889-73c4bf75f232?project=antler-vc",
+ },
+ ];
+
+ const notificationsCount = notifications.length;
+ return (
+ <>
+
+
+
+
+
+
+
+ {notifications.map((notification) => (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ))}
+
+
+ >
+ );
+};
+export default Notification;
diff --git a/src/components/Navigation/UpdateChecker.tsx b/src/components/Navigation/UpdateChecker.tsx
new file mode 100644
index 000000000..06ce3c0ad
--- /dev/null
+++ b/src/components/Navigation/UpdateChecker.tsx
@@ -0,0 +1,131 @@
+import { useState, useEffect } from "react";
+import createPersistedState from "use-persisted-state";
+import { differenceInDays } from "date-fns";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import {
+ MenuItem,
+ ListItemText,
+ ListItemSecondaryAction,
+} from "@material-ui/core";
+import OpenInNewIcon from "@material-ui/icons/OpenInNew";
+
+import meta from "../../../package.json";
+import WIKI_LINKS from "constants/wikiLinks";
+
+const useLastCheckedUpdateState = createPersistedState(
+ "__ROWY__LAST_CHECKED_UPDATE"
+);
+export const useLatestUpdateState = createPersistedState(
+ "__ROWY__LATEST_UPDATE"
+);
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ secondaryAction: { pointerEvents: "none" },
+ secondaryIcon: {
+ display: "block",
+ color: theme.palette.action.active,
+ },
+ })
+);
+
+export default function UpdateChecker() {
+ const classes = useStyles();
+
+ const [lastCheckedUpdate, setLastCheckedUpdate] = useLastCheckedUpdateState<
+ string
+ >();
+ const [latestUpdate, setLatestUpdate] = useLatestUpdateState>(null);
+
+ const [checkState, setCheckState] = useState(
+ null
+ );
+
+ const checkForUpdate = async () => {
+ setCheckState("LOADING");
+
+ // https://docs.github.com/en/rest/reference/repos#get-the-latest-release
+ const endpoint = meta.repository.url
+ .replace("github.com", "api.github.com/repos")
+ .replace(/.git$/, "/releases/latest");
+ try {
+ const res = await fetch(endpoint, {
+ headers: {
+ Accept: "application/vnd.github.v3+json",
+ },
+ });
+ const json = await res.json();
+
+ if (json.tag_name > "v" + meta.version) {
+ setLatestUpdate(json);
+ setCheckState(null);
+ } else {
+ setCheckState("NO_UPDATE");
+ }
+
+ setLastCheckedUpdate(new Date().toISOString());
+ } catch (e) {
+ console.error(e);
+ setLatestUpdate(null);
+ setCheckState("NO_UPDATE");
+ }
+ };
+
+ // Check for new updates on page load, if last check was more than 7 days ago
+ useEffect(() => {
+ if (!lastCheckedUpdate) checkForUpdate();
+ else if (differenceInDays(new Date(), new Date(lastCheckedUpdate)) > 7)
+ checkForUpdate();
+ }, [lastCheckedUpdate]);
+
+ // Verify latest update is not installed yet
+ useEffect(() => {
+ if (latestUpdate?.tag_name <= "v" + meta.version) setLatestUpdate(null);
+ }, [latestUpdate, setLatestUpdate]);
+
+ if (checkState === "LOADING")
+ return Checking for updates… ;
+ if (checkState === "NO_UPDATE")
+ return No updates available ;
+ if (latestUpdate === null)
+ return Check for updates ;
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+}
diff --git a/src/components/Navigation/UserMenu.tsx b/src/components/Navigation/UserMenu.tsx
new file mode 100644
index 000000000..fe753f67a
--- /dev/null
+++ b/src/components/Navigation/UserMenu.tsx
@@ -0,0 +1,246 @@
+import { useState, useRef } from "react";
+import { Link } from "react-router-dom";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import {
+ IconButton,
+ IconButtonProps,
+ Avatar,
+ Menu,
+ MenuItem,
+ ListItem,
+ ListItemAvatar,
+ ListItemText,
+ ListItemSecondaryAction,
+ Link as MuiLink,
+ Divider,
+ Badge,
+} from "@material-ui/core";
+import AccountCircleIcon from "@material-ui/icons/AccountCircle";
+import ArrowRightIcon from "@material-ui/icons/ArrowRight";
+
+import UpdateChecker, { useLatestUpdateState } from "./UpdateChecker";
+import { useAppContext } from "contexts/AppContext";
+import routes from "constants/routes";
+import { projectId } from "../../firebase";
+import meta from "../../../package.json";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ spacer: {
+ width: 48,
+ height: 48,
+ },
+
+ iconButton: {},
+ avatar: {
+ "$iconButton &": {
+ width: 24,
+ height: 24,
+ },
+ },
+
+ paper: { minWidth: 160 },
+
+ // divider: { margin: theme.spacing(1, 2) },
+
+ secondaryAction: { pointerEvents: "none" },
+ secondaryIcon: {
+ display: "block",
+ color: theme.palette.action.active,
+ },
+
+ subMenu: { marginTop: theme.spacing(-0.5) },
+
+ version: {
+ userSelect: "none",
+ color: theme.palette.text.disabled,
+ margin: 0,
+ },
+ })
+);
+
+export default function UserMenu(props: IconButtonProps) {
+ const classes = useStyles();
+
+ const anchorEl = useRef(null);
+ const [open, setOpen] = useState(false);
+ const [themeSubMenu, setThemeSubMenu] = useState(null);
+ const [latestUpdate] = useLatestUpdateState>();
+
+ const {
+ currentUser,
+ userDoc,
+ theme,
+ themeOverridden,
+ setTheme,
+ setThemeOverridden,
+ } = useAppContext();
+ if (!currentUser || !userDoc || !userDoc?.state?.doc)
+ return
;
+
+ const displayName = userDoc?.state?.doc?.user?.displayName;
+ const avatarUrl = userDoc?.state?.doc?.user?.photoURL;
+ const email = userDoc?.state?.doc?.user?.email;
+
+ const avatar = avatarUrl ? (
+
+ ) : (
+
+ );
+
+ const changeTheme = (option: "system" | "light" | "dark") => {
+ switch (option) {
+ case "system":
+ setThemeOverridden(false);
+ return;
+
+ case "light":
+ setTheme("light");
+ break;
+
+ case "dark":
+ setTheme("dark");
+ break;
+
+ default:
+ break;
+ }
+ setThemeOverridden(true);
+ setThemeSubMenu(null);
+ setOpen(false);
+ };
+
+ return (
+ <>
+ setOpen(true)}
+ className={classes.iconButton}
+ >
+ {latestUpdate?.tag_name > "v" + meta.version ? (
+
+ {avatar}
+
+ ) : (
+ avatar
+ )}
+
+
+
+ >
+ );
+}
diff --git a/src/components/Navigation/index.tsx b/src/components/Navigation/index.tsx
new file mode 100644
index 000000000..e24a476bd
--- /dev/null
+++ b/src/components/Navigation/index.tsx
@@ -0,0 +1,103 @@
+import React, { useState, useEffect } from "react";
+import _find from "lodash/find";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { AppBar, Toolbar, IconButton } from "@material-ui/core";
+import MenuIcon from "@material-ui/icons/Menu";
+
+import Breadcrumbs from "./Breadcrumbs";
+import NavDrawer from "./NavDrawer";
+
+// import { DRAWER_COLLAPSED_WIDTH } from "components/SideDrawer";
+import { useRowyContext } from "contexts/RowyContext";
+import UserMenu from "./UserMenu";
+
+export const APP_BAR_HEIGHT = 56;
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ appBar: {
+ // paddingRight: DRAWER_COLLAPSED_WIDTH,
+ height: APP_BAR_HEIGHT,
+ [theme.breakpoints.down("md")]: { paddingRight: 0 },
+
+ backgroundColor: theme.palette.background.default,
+ },
+
+ toolbar: {
+ height: APP_BAR_HEIGHT,
+ minHeight: "auto",
+ minWidth: 0,
+ maxWidth: "none",
+ padding: theme.spacing(0, 2),
+ },
+
+ breadcrumbs: { flex: 1 },
+ })
+);
+
+export default function Navigation({
+ children,
+ tableCollection,
+}: React.PropsWithChildren<{ tableCollection: string }>) {
+ const { tables } = useRowyContext();
+ const classes = useStyles();
+
+ const [open, setOpen] = useState(false);
+ useEffect(() => {
+ setOpen(false);
+ }, [tableCollection]);
+
+ // Find the matching section for the current route
+ const currentSection = _find(tables, [
+ "collection",
+ tableCollection?.split("/")[0],
+ ])?.section;
+ const currentTable = tableCollection?.split("/")[0];
+
+ useEffect(() => {
+ const name =
+ _find(tables, ["collection", currentTable])?.name || currentTable;
+ document.title = `${name} | Rowy`;
+
+ return () => {
+ document.title = "Rowy";
+ };
+ }, [currentTable]);
+
+ return (
+ <>
+
+
+ setOpen(true)}
+ size="large"
+ edge="start"
+ >
+
+
+
+
+
+
+ {/* */}
+
+
+
+ setOpen(false)}
+ />
+
+ {children}
+ >
+ );
+}
diff --git a/src/components/ProjectSettings/form.tsx b/src/components/ProjectSettings/form.tsx
new file mode 100644
index 000000000..4f2fc4ef3
--- /dev/null
+++ b/src/components/ProjectSettings/form.tsx
@@ -0,0 +1,73 @@
+import { FieldType } from "@antlerengineering/form-builder";
+import _startCase from "lodash/startCase";
+import { authOptions } from "firebase/firebaseui";
+
+import { Link } from "@material-ui/core";
+import OpenInNewIcon from "@material-ui/icons/OpenInNew";
+import WIKI_LINKS from "constants/wikiLinks";
+
+export const projectSettingsForm = [
+ {
+ type: FieldType.contentHeader,
+ name: "_contentHeading_signInOptions",
+ label: "Authentication",
+ },
+ {
+ type: FieldType.multiSelect,
+ name: "signInOptions",
+ label: "Sign-In Options",
+ options: Object.keys(authOptions).map((option) => ({
+ value: option,
+ label: _startCase(option).replace("Github", "GitHub"),
+ })),
+ defaultValue: ["google"],
+ required: true,
+ assistiveText: (
+ <>
+ Before enabling a new sign-in option, make sure it’s configured in your
+ Firebase project.
+
+
+ How to configure sign-in options
+
+
+ >
+ ) as any,
+ },
+ {
+ type: FieldType.contentHeader,
+ name: "_contentHeading_cloudRun",
+ label: "Functions Builder",
+ },
+ {
+ type: FieldType.shortText,
+ name: "buildUrl",
+ label: "Cloud Run Trigger URL",
+ format: "url",
+ assistiveText: (
+ <>
+ A Cloud Run instance is required to build and deploy Rowy Cloud
+ Functions.
+
+ Learn more
+
+
+
+ To deploy the Cloud Run instance, click the button bellow and follow the
+ Cloud Shell prompts.
+ >
+ ) as any,
+ },
+];
diff --git a/src/components/ProjectSettings/index.tsx b/src/components/ProjectSettings/index.tsx
new file mode 100644
index 000000000..efaa5adb4
--- /dev/null
+++ b/src/components/ProjectSettings/index.tsx
@@ -0,0 +1,62 @@
+import { FormDialog } from "@antlerengineering/form-builder";
+import { projectSettingsForm } from "./form";
+
+import useDoc, { DocActions } from "hooks/useDoc";
+import { IFormDialogProps } from "components/Table/ColumnMenu/NewColumn";
+import { Button } from "@material-ui/core";
+
+export interface IProjectSettings
+ extends Pick {
+ handleOpenBuilderInstaller: () => void;
+}
+
+export default function ProjectSettings({
+ handleClose,
+ handleOpenBuilderInstaller,
+}: IProjectSettings) {
+ const [settingsState, settingsDispatch] = useDoc({
+ path: "_rowy_/settings",
+ });
+ const [publicSettingsState, publicSettingsDispatch] = useDoc({
+ path: "_rowy_/publicSettings",
+ });
+
+ if (settingsState.loading || publicSettingsState.loading) return null;
+
+ const handleSubmit = (v) => {
+ const { signInOptions, ...values } = v;
+
+ settingsDispatch({ action: DocActions.update, data: values });
+ publicSettingsDispatch({
+ action: DocActions.update,
+ data: { signInOptions },
+ });
+ };
+
+ const onOpenBuilderInstaller = () => {
+ handleClose();
+ window.open(
+ "https://deploy.cloud.run/?git_repo=https://github.com/rowyio/FunctionsBuilder.git",
+ "_blank"
+ );
+ handleOpenBuilderInstaller();
+ };
+
+ const hasCloudRunConfig = !!settingsState.doc.buildUrl;
+
+ return (
+ One click deploy
+ )
+ }
+ />
+ );
+}
diff --git a/src/components/RenderedHtml.tsx b/src/components/RenderedHtml.tsx
new file mode 100644
index 000000000..17808eed8
--- /dev/null
+++ b/src/components/RenderedHtml.tsx
@@ -0,0 +1,110 @@
+import DOMPurify from "dompurify";
+import clsx from "clsx";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: {
+ maxWidth: "33em",
+ ...theme.typography.body2,
+
+ "& * + *": {
+ marginTop: "1em !important",
+ },
+
+ "& h1, & h2, & h3, & h4, & h5, & h6": {
+ fontFamily: '"Europa", "Open Sans", sans-serif',
+ margin: 0,
+ lineHeight: 1.2,
+ fontWeight: "bold",
+ },
+ "& p": {
+ margin: 0,
+ marginTop: "inherit",
+ },
+
+ "& a": {
+ fontWeight: "bold",
+ color: theme.palette.primary.main,
+ textDecoration: "underline",
+
+ "&:hover": { color: theme.palette.primary.dark },
+ },
+
+ "& ul, & ol": {
+ margin: 0,
+ paddingLeft: "1.5em",
+ },
+ "& li + li": {
+ marginTop: "0.5em",
+ },
+
+ "& table": {
+ borderCollapse: "collapse",
+ },
+
+ "& table th, & table td": {
+ border: `1px solid ${theme.palette.divider}`,
+ padding: "0.4rem",
+ },
+ "& figure": {
+ display: "table",
+ margin: "1rem auto",
+ },
+ "& figure figcaption": {
+ color: "#999",
+ display: "block",
+ marginTop: "0.25rem",
+ textAlign: "center",
+ },
+ "& hr": {
+ borderColor: `1px solid ${theme.palette.divider}`,
+ borderWidth: "1px 0 0 0",
+ },
+ "& code": {
+ backgroundColor: "#e8e8e8",
+ borderRadius: theme.shape.borderRadius,
+ padding: "0.1rem 0.2rem",
+ fontFamily: theme.typography.fontFamilyMono,
+ },
+ "& pre": {
+ fontFamily: theme.typography.fontFamilyMono,
+ },
+ '& .mceContent-body:not([dir="rtl"]) blockquote': {
+ borderLeft: `2px solid ${theme.palette.divider}`,
+ marginLeft: "1.5rem",
+ paddingLeft: "1rem",
+ },
+ '& .mceContent-body[dir="rtl"] blockquote': {
+ borderRight: `2px solid ${theme.palette.divider}`,
+ marginRight: "1.5rem",
+ paddingRight: "1rem",
+ },
+ },
+ })
+);
+
+export interface IRenderedHtmlProps
+ extends React.DetailedHTMLProps<
+ React.HTMLAttributes,
+ HTMLDivElement
+ > {
+ html: string;
+}
+
+export default function RenderedHtml({
+ html,
+ className,
+ ...props
+}: IRenderedHtmlProps) {
+ const classes = useStyles();
+
+ return (
+
+ );
+}
diff --git a/src/components/RichTextEditor.tsx b/src/components/RichTextEditor.tsx
new file mode 100644
index 000000000..f8d473761
--- /dev/null
+++ b/src/components/RichTextEditor.tsx
@@ -0,0 +1,145 @@
+import { useState } from "react";
+import clsx from "clsx";
+
+import "tinymce/tinymce.min.js";
+import "tinymce/themes/silver";
+import "tinymce/skins/ui/oxide/skin.min.css";
+import "tinymce/skins/ui/oxide/content.min.css";
+import "tinymce/plugins/autoresize";
+import "tinymce/plugins/lists";
+import "tinymce/plugins/link";
+import "tinymce/plugins/image";
+import "tinymce/plugins/paste";
+import "tinymce/plugins/help";
+import "tinymce/plugins/code";
+import { Editor } from "@tinymce/tinymce-react";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { useTheme } from "@material-ui/core";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ "@global": {
+ body: {
+ fontFamily: theme.typography.fontFamily + " !important",
+ },
+ },
+
+ root: {
+ "& .tox": {
+ "&.tox-tinymce": {
+ borderRadius: theme.shape.borderRadius,
+ border: "none",
+ backgroundColor:
+ theme.palette.mode === "light"
+ ? "rgba(0, 0, 0, 0.09)"
+ : "rgba(255, 255, 255, 0.09)",
+
+ transition: theme.transitions.create("background-color", {
+ duration: theme.transitions.duration.shorter,
+ easing: theme.transitions.easing.easeOut,
+ }),
+
+ "&:hover": {
+ backgroundColor:
+ theme.palette.mode === "light"
+ ? "rgba(0, 0, 0, 0.13)"
+ : "rgba(255, 255, 255, 0.13)",
+ },
+ },
+
+ "& .tox-sidebar-wrap": {
+ margin: 1,
+ },
+
+ "& .tox-toolbar-overlord, & .tox-edit-area__iframe, & .tox-toolbar__primary": {
+ background: "transparent",
+ borderRadius: (theme.shape.borderRadius as number) - 1,
+ },
+
+ "& .tox-toolbar__primary": { padding: theme.spacing(0.5, 0) },
+ "& .tox-toolbar__group": {
+ padding: theme.spacing(0, 1),
+ border: "none !important",
+ },
+
+ "& .tox-tbtn": {
+ borderRadius: theme.shape.borderRadius,
+ color: theme.palette.text.secondary,
+ cursor: "pointer",
+ margin: 0,
+
+ transition: theme.transitions.create(["color", "background-color"], {
+ duration: theme.transitions.duration.shortest,
+ }),
+
+ "&:hover": {
+ color: theme.palette.text.primary,
+ backgroundColor: "transparent",
+ },
+
+ "& svg": { fill: "currentColor" },
+ },
+
+ "& .tox-tbtn--enabled, & .tox-tbtn--enabled:hover": {
+ backgroundColor: theme.palette.action.selected + " !important",
+ color: theme.palette.text.primary,
+ },
+ },
+ },
+
+ focus: {
+ "& .tox.tox-tinymce": {
+ backgroundColor:
+ (theme.palette.mode === "light"
+ ? "rgba(0, 0, 0, 0.09)"
+ : "rgba(255, 255, 255, 0.09)") + "!important",
+ },
+ },
+ })
+);
+
+export interface IRichTextEditorProps {
+ value?: string;
+ onChange: (value: string) => void;
+ disabled?: boolean;
+}
+
+export default function RichTextEditor({
+ value,
+ onChange,
+ disabled,
+}: IRichTextEditorProps) {
+ const classes = useStyles();
+ const theme = useTheme();
+ const [focus, setFocus] = useState(false);
+
+ return (
+
+ setFocus(true)}
+ onBlur={() => setFocus(false)}
+ />
+
+ );
+}
diff --git a/src/components/RichTooltip.tsx b/src/components/RichTooltip.tsx
new file mode 100644
index 000000000..20a396c74
--- /dev/null
+++ b/src/components/RichTooltip.tsx
@@ -0,0 +1,112 @@
+import React, { useState } from "react";
+import clsx from "clsx";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { Tooltip, TooltipProps, Button, ButtonProps } from "@material-ui/core";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ tooltip: {
+ backgroundColor: theme.palette.background.default,
+ boxShadow: theme.shadows[2],
+
+ ...theme.typography.caption,
+ color: theme.palette.text.primary,
+ padding: 0,
+ },
+
+ arrow: {
+ "&::before": {
+ backgroundColor: theme.palette.background.default,
+ boxShadow: theme.shadows[2],
+ },
+ },
+
+ grid: {
+ padding: theme.spacing(2),
+ cursor: "default",
+
+ display: "grid",
+ gridTemplateColumns: "40px auto",
+ gap: theme.spacing(1, 2),
+ },
+ emoji: {
+ fontSize: `${40 / 16}rem`,
+ fontWeight: 400,
+ fontFamily:
+ "apple color emoji, segoe ui emoji, noto color emoji, android emoji, emojisymbols, emojione mozilla, twemoji mozilla, segoe ui symbol",
+ },
+ message: {
+ alignSelf: "center",
+ },
+ dismissButton: {
+ marginLeft: theme.spacing(-1),
+ gridColumn: 2,
+ justifySelf: "flex-start",
+ },
+ })
+);
+
+export interface IRichTooltipProps extends Partial {
+ render: (props: {
+ openTooltip: () => void;
+ closeTooltip: () => void;
+ toggleTooltip: () => void;
+ }) => TooltipProps["children"];
+
+ emoji?: React.ReactNode;
+ message: React.ReactNode;
+ dismissButtonText?: React.ReactNode;
+ dismissButtonProps?: Partial;
+}
+
+export default function RichTooltip({
+ render,
+ emoji,
+ message,
+ dismissButtonText,
+ dismissButtonProps,
+ ...props
+}: IRichTooltipProps) {
+ const classes = useStyles();
+ const [open, setOpen] = useState(false);
+
+ const openTooltip = () => setOpen(true);
+ const closeTooltip = () => setOpen(false);
+ const toggleTooltip = () => setOpen((state) => !state);
+
+ return (
+
+ {emoji}
+
+ {message}
+
+ {dismissButtonText && (
+
+ {dismissButtonText}
+
+ )}
+
+ }
+ {...props}
+ >
+ {render({ openTooltip, closeTooltip, toggleTooltip })}
+
+ );
+}
diff --git a/src/components/SideDrawer/Form/Autosave.tsx b/src/components/SideDrawer/Form/Autosave.tsx
new file mode 100644
index 000000000..08fc30805
--- /dev/null
+++ b/src/components/SideDrawer/Form/Autosave.tsx
@@ -0,0 +1,75 @@
+import { useEffect } from "react";
+import { useDebounce } from "use-debounce";
+import _isEqual from "lodash/isEqual";
+import _pick from "lodash/pick";
+import _pickBy from "lodash/pickBy";
+
+import { Control, UseFormMethods, useWatch } from "react-hook-form";
+import { Values } from "./utils";
+
+import { useRowyContext } from "contexts/RowyContext";
+import { RowyState } from "hooks/useRowy";
+
+export interface IAutosaveProps {
+ control: Control;
+ docRef: firebase.default.firestore.DocumentReference;
+ row: any;
+ reset: UseFormMethods["reset"];
+ dirtyFields: UseFormMethods["formState"]["dirtyFields"];
+}
+
+const getEditables = (values: Values, tableState?: RowyState) =>
+ _pick(
+ values,
+ (tableState &&
+ (Array.isArray(tableState?.columns)
+ ? tableState?.columns
+ : Object.values(tableState?.columns)
+ ).map((c) => c.key)) ??
+ []
+ );
+
+export default function Autosave({
+ control,
+ docRef,
+ row,
+ reset,
+ dirtyFields,
+}: IAutosaveProps) {
+ const { tableState, updateCell } = useRowyContext();
+
+ const values = useWatch({ control });
+ const [debouncedValue] = useDebounce(getEditables(values, tableState), 1000, {
+ equalityFn: _isEqual,
+ });
+
+ useEffect(() => {
+ if (!row || !row.ref) return;
+ if (row.ref.id !== docRef.id) return;
+ if (!updateCell) return;
+
+ // Get only fields that have had their value updated by the user
+ const updatedValues = _pickBy(
+ _pickBy(debouncedValue, (_, key) => dirtyFields[key]),
+ (value, key) => !_isEqual(value, row[key])
+ );
+ console.log(debouncedValue, row);
+ console.log(updatedValues, dirtyFields);
+ if (Object.keys(updatedValues).length === 0) return;
+
+ // Update the document
+ Object.entries(updatedValues).forEach(([key, value]) =>
+ updateCell(
+ row.ref,
+ key,
+ value,
+ // After the cell is updated, set this field to be not dirty
+ // so it doesn’t get updated again when a different field in the form
+ // is updated + make sure the new value is kept after reset
+ () => reset({ ...values, [key]: value })
+ )
+ );
+ }, [debouncedValue]);
+
+ return null;
+}
diff --git a/src/components/SideDrawer/Form/FieldSkeleton.tsx b/src/components/SideDrawer/Form/FieldSkeleton.tsx
new file mode 100644
index 000000000..8f56ed466
--- /dev/null
+++ b/src/components/SideDrawer/Form/FieldSkeleton.tsx
@@ -0,0 +1,17 @@
+import { useTheme } from "@material-ui/core";
+import { Skeleton } from "@material-ui/core";
+import { SkeletonProps } from "@material-ui/lab";
+
+export default function FieldSkeleton(props: SkeletonProps) {
+ const theme = useTheme();
+ return (
+
+ );
+}
diff --git a/src/components/SideDrawer/Form/FieldWrapper.tsx b/src/components/SideDrawer/Form/FieldWrapper.tsx
new file mode 100644
index 000000000..c6dafe9dc
--- /dev/null
+++ b/src/components/SideDrawer/Form/FieldWrapper.tsx
@@ -0,0 +1,131 @@
+import React, { Suspense } from "react";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { Grid, Typography, IconButton } from "@material-ui/core";
+import DebugIcon from "@material-ui/icons/BugReportOutlined";
+import LaunchIcon from "@material-ui/icons/Launch";
+import LockIcon from "@material-ui/icons/Lock";
+
+import ErrorBoundary from "components/ErrorBoundary";
+import FieldSkeleton from "./FieldSkeleton";
+
+import { FieldType } from "constants/fields";
+import { getFieldProp } from "components/fields";
+import { projectId } from "../../../firebase";
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ header: {
+ paddingBottom: theme.spacing(1),
+ color: theme.palette.text.secondary,
+
+ "& svg": {
+ display: "block",
+ fontSize: 18,
+ },
+ },
+ iconContainer: {
+ marginRight: theme.spacing(1),
+ },
+
+ label: {
+ ...theme.typography.caption,
+ lineHeight: "18px",
+ fontWeight: 500,
+ },
+
+ disabledText: {
+ paddingLeft: theme.spacing(18 / 8 + 1),
+ color: theme.palette.text.disabled,
+
+ whiteSpace: "normal",
+ wordBreak: "break-all",
+ },
+ launchButton: { margin: theme.spacing(-3, -1.5, 0, 0) },
+ })
+);
+
+export interface IFieldWrapperProps {
+ children?: React.ReactNode;
+ type: FieldType | "debug";
+ name?: string;
+ label?: React.ReactNode;
+ debugText?: React.ReactNode;
+ disabled?: boolean;
+}
+
+export default function FieldWrapper({
+ children,
+ type,
+ name,
+ label,
+ debugText,
+ disabled,
+}: IFieldWrapperProps) {
+ const classes = useStyles();
+
+ return (
+
+
+
+ {type === "debug" ? : getFieldProp("icon", type)}
+
+
+ {label}
+
+ {disabled && (
+
+
+
+ )}
+
+
+
+ }>
+ {children ??
+ (!debugText && (
+
+ This field cannot be edited here
+
+ ))}
+
+
+
+ {debugText && (
+
+
+
+ {debugText}
+
+
+
+
+
+
+
+
+
+ )}
+
+ );
+}
diff --git a/src/components/SideDrawer/Form/Label.tsx b/src/components/SideDrawer/Form/Label.tsx
new file mode 100644
index 000000000..2764b75e2
--- /dev/null
+++ b/src/components/SideDrawer/Form/Label.tsx
@@ -0,0 +1,45 @@
+import { makeStyles, createStyles } from "@material-ui/styles";
+import {
+ FormLabel,
+ FormLabelProps,
+ Tooltip,
+ IconButton,
+} from "@material-ui/core";
+import HelpIcon from "@material-ui/icons/HelpOutline";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: {
+ display: "block",
+ marginBottom: theme.spacing(1),
+ },
+ })
+);
+
+export interface ILabelProps extends FormLabelProps {
+ label?: React.ReactNode;
+ hint?: React.ReactNode;
+}
+
+export default function Label({
+ label,
+ children,
+ hint,
+ ...props
+}: ILabelProps) {
+ const classes = useStyles();
+
+ return (
+
+ {label || children}
+
+ {hint && (
+
+
+
+
+
+ )}
+
+ );
+}
diff --git a/src/components/SideDrawer/Form/Reset.tsx b/src/components/SideDrawer/Form/Reset.tsx
new file mode 100644
index 000000000..0bd9c7ef7
--- /dev/null
+++ b/src/components/SideDrawer/Form/Reset.tsx
@@ -0,0 +1,50 @@
+import { useEffect } from "react";
+import { UseFormMethods } from "react-hook-form";
+import _pickBy from "lodash/pickBy";
+import _isEqual from "lodash/isEqual";
+
+import { Values } from "./utils";
+
+export interface IResetProps {
+ defaultValues: Values;
+ dirtyFields: UseFormMethods["formState"]["dirtyFields"];
+ reset: UseFormMethods["reset"];
+ getValues: UseFormMethods["getValues"];
+}
+
+/**
+ * Reset the form’s values and errors when the Firestore doc’s data updates
+ */
+export default function Reset({
+ defaultValues,
+ dirtyFields,
+ reset,
+ getValues,
+}: IResetProps) {
+ useEffect(
+ () => {
+ const resetValues = { ...defaultValues };
+ const currentValues = getValues();
+
+ // If the field is dirty, (i.e. the user input a value but it hasn’t been)
+ // saved to the db yet, keep its current value and keep it marked as dirty
+ for (const [field, isDirty] of Object.entries(dirtyFields)) {
+ if (isDirty) {
+ resetValues[field] = currentValues[field];
+ }
+ }
+
+ // Compare currentValues to resetValues
+ const diff = _pickBy(getValues(), (v, k) => !_isEqual(v, resetValues[k]));
+ // Reset if needed & keep the current dirty fields
+ if (Object.keys(diff).length > 0) {
+ reset(resetValues, { isDirty: true, dirtyFields: true });
+ }
+ },
+ // `defaultValues` is the `initialValue` of each field type +
+ // the current value in the Firestore doc
+ [JSON.stringify(defaultValues)]
+ );
+
+ return null;
+}
diff --git a/src/components/SideDrawer/Form/index.tsx b/src/components/SideDrawer/Form/index.tsx
new file mode 100644
index 000000000..d6f42e6be
--- /dev/null
+++ b/src/components/SideDrawer/Form/index.tsx
@@ -0,0 +1,122 @@
+import React from "react";
+import { useForm } from "react-hook-form";
+import _sortBy from "lodash/sortBy";
+import _isEmpty from "lodash/isEmpty";
+
+import { Grid } from "@material-ui/core";
+
+import { Values } from "./utils";
+import { getFieldProp } from "components/fields";
+import { IFieldConfig } from "components/fields/types";
+import Autosave from "./Autosave";
+import Reset from "./Reset";
+import FieldWrapper from "./FieldWrapper";
+
+import { useAppContext } from "contexts/AppContext";
+import { useRowyContext } from "contexts/RowyContext";
+
+export interface IFormProps {
+ values: Values;
+}
+
+export default function Form({ values }: IFormProps) {
+ const { tableState } = useRowyContext();
+ const { userDoc } = useAppContext();
+ const userDocHiddenFields =
+ userDoc.state.doc?.tables?.[`${tableState!.tablePath}`]?.hiddenFields ?? [];
+
+ const fields = _sortBy(Object.values(tableState!.columns), "index").filter(
+ (f) => !userDocHiddenFields.includes(f.name)
+ );
+
+ // Get initial values from fields config. This won’t be written to the db
+ // when the SideDrawer is opened. Only dirty fields will be written
+ const initialValues = fields.reduce(
+ (a, { key, type }) => ({ ...a, [key]: getFieldProp("initialValue", type) }),
+ {}
+ );
+ const { ref: docRef, ...rowValues } = values;
+ const defaultValues = { ...initialValues, ...rowValues };
+
+ const { control, reset, formState, getValues } = useForm({
+ mode: "onBlur",
+ defaultValues,
+ });
+ const { dirtyFields } = formState;
+
+ // const { sideDrawerRef } = useRowyContext();
+ // useEffect(() => {
+ // const column = sideDrawerRef?.current?.cell?.column;
+ // if (!column) return;
+
+ // const elem = document.getElementById(`sidedrawer-label-${column}`)
+ // ?.parentNode as HTMLElement;
+
+ // // Time out for double-clicking on cells, which can open the null editor
+ // setTimeout(() => elem?.scrollIntoView({ behavior: "smooth" }), 200);
+ // }, [sideDrawerRef?.current]);
+
+ return (
+
+ );
+}
diff --git a/src/components/SideDrawer/Form/utils.ts b/src/components/SideDrawer/Form/utils.ts
new file mode 100644
index 000000000..a4897af87
--- /dev/null
+++ b/src/components/SideDrawer/Form/utils.ts
@@ -0,0 +1,55 @@
+import { Control } from "react-hook-form";
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { FieldType } from "constants/fields";
+import { colord } from "colord";
+
+export interface IFieldProps {
+ control: Control;
+ name: string;
+ docRef: firebase.default.firestore.DocumentReference;
+ editable?: boolean;
+}
+
+export type Values = Record;
+export type Field = {
+ type?: FieldType;
+ name: string;
+ label?: string;
+ [key: string]: any;
+};
+export type Fields = (Field | ((values: Values) => Field))[];
+
+export const useFieldStyles = makeStyles((theme) =>
+ createStyles({
+ root: {
+ borderRadius: theme.shape.borderRadius,
+ padding: theme.spacing(0.75, 1, 0.75, 1.5),
+
+ backgroundColor: theme.palette.action.input,
+ boxShadow: `0 0 0 1px ${
+ theme.palette.mode === "dark"
+ ? colord(theme.palette.divider)
+ .alpha(colord(theme.palette.divider).alpha() / 2)
+ .toHslString()
+ : theme.palette.divider
+ } inset`,
+
+ "&.Mui-disabled": {
+ backgroundColor:
+ theme.palette.mode === "dark"
+ ? "transparent"
+ : theme.palette.action.disabledBackground,
+ },
+
+ width: "100%",
+ minHeight: 32,
+
+ display: "flex",
+ textAlign: "left",
+ alignItems: "center",
+
+ ...theme.typography.body2,
+ color: theme.palette.text.primary,
+ },
+ })
+);
diff --git a/src/components/SideDrawer/index.tsx b/src/components/SideDrawer/index.tsx
new file mode 100644
index 000000000..a9d879d77
--- /dev/null
+++ b/src/components/SideDrawer/index.tsx
@@ -0,0 +1,170 @@
+import React, { useState, useEffect } from "react";
+import clsx from "clsx";
+import _isNil from "lodash/isNil";
+import _isEmpty from "lodash/isEmpty";
+import queryString from "query-string";
+
+import { Drawer, Fab } from "@material-ui/core";
+import ChevronIcon from "@material-ui/icons/KeyboardArrowLeft";
+import ChevronUpIcon from "@material-ui/icons/KeyboardArrowUp";
+import ChevronDownIcon from "@material-ui/icons/KeyboardArrowDown";
+
+import Form from "./Form";
+import ErrorBoundary from "components/ErrorBoundary";
+
+import { useStyles } from "./useStyles";
+import { useRowyContext } from "contexts/RowyContext";
+import useDoc from "hooks/useDoc";
+
+export const DRAWER_WIDTH = 512;
+export const DRAWER_COLLAPSED_WIDTH = 36;
+
+type SelectedCell = { row: number; column: string } | null;
+export type SideDrawerRef = {
+ cell: SelectedCell;
+ setCell: React.Dispatch>;
+ open: boolean;
+ setOpen: React.Dispatch>;
+};
+
+export default function SideDrawer() {
+ const classes = useStyles();
+ const { tableState, dataGridRef, sideDrawerRef } = useRowyContext();
+
+ const [cell, setCell] = useState(null);
+ const [open, setOpen] = useState(false);
+ if (sideDrawerRef) sideDrawerRef.current = { cell, setCell, open, setOpen };
+
+ const disabled = !open && (!cell || _isNil(cell.row));
+ useEffect(() => {
+ if (disabled && setOpen) setOpen(false);
+ }, [disabled]);
+
+ const handleNavigate = (direction: "up" | "down") => () => {
+ if (!tableState?.rows) return;
+
+ let row = cell!.row;
+ if (direction === "up" && row > 0) row -= 1;
+ if (direction === "down" && row < tableState.rows.length - 1) row += 1;
+
+ setCell!((cell) => ({ column: cell!.column, row }));
+
+ const idx = tableState?.columns[cell!.column]?.index;
+ dataGridRef?.current?.selectCell({ rowIdx: row, idx });
+ };
+
+ const [urlDocState, dispatchUrlDoc] = useDoc({});
+ useEffect(() => {
+ if (urlDocState.doc) setOpen(true);
+ }, [urlDocState]);
+
+ useEffect(() => {
+ setOpen(false);
+ dispatchUrlDoc({ path: "", doc: null });
+ }, [window.location.pathname]);
+
+ useEffect(() => {
+ const rowRef = queryString.parse(window.location.search).rowRef as string;
+ if (rowRef) dispatchUrlDoc({ path: decodeURIComponent(rowRef) });
+ }, []);
+
+ useEffect(() => {
+ if (cell && tableState?.rows[cell.row]) {
+ window.history.pushState(
+ "",
+ `${tableState?.tablePath}`,
+ `${window.location.pathname}?rowRef=${encodeURIComponent(
+ tableState?.rows[cell.row].ref.path
+ )}`
+ );
+ // console.log(tableState?.tablePath, tableState?.rows[cell.row].id);
+ if (urlDocState.doc) {
+ urlDocState.unsubscribe();
+ dispatchUrlDoc({ path: "", doc: null });
+ }
+ }
+ }, [cell]);
+
+ return (
+
+
+
+
+ {open &&
+ (urlDocState.doc || cell) &&
+ !_isEmpty(tableState?.columns) && (
+
+ )}
+
+
+
+ {open && (
+
+
+
+
+
+ = tableState.rows.length - 1
+ }
+ onClick={handleNavigate("down")}
+ >
+
+
+
+ )}
+
+
+ {
+ if (setOpen) setOpen((o) => !o);
+ }}
+ >
+
+
+
+
+
+ );
+}
diff --git a/src/components/SideDrawer/useStyles.ts b/src/components/SideDrawer/useStyles.ts
new file mode 100644
index 000000000..1a2b8a645
--- /dev/null
+++ b/src/components/SideDrawer/useStyles.ts
@@ -0,0 +1,112 @@
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { DRAWER_WIDTH, DRAWER_COLLAPSED_WIDTH } from "./index";
+import { APP_BAR_HEIGHT } from "components/Navigation";
+import { TABLE_HEADER_HEIGHT } from "components/Table/TableHeader";
+
+export const useStyles = makeStyles((theme) =>
+ createStyles({
+ open: {},
+ disabled: {
+ "& $paper": {
+ transform: `translateX(${DRAWER_WIDTH + 32}px)`,
+ boxShadow: "none",
+ },
+ },
+
+ drawer: {
+ width: DRAWER_WIDTH,
+ flexShrink: 0,
+ whiteSpace: "nowrap",
+ },
+
+ paper: {
+ border: "none",
+ boxShadow: theme.shadows[4].replace(/, 0 (\d+px)/g, ", -$1 0"),
+ borderTopLeftRadius: `${(theme.shape.borderRadius as number) * 3}px`,
+ borderBottomLeftRadius: `${(theme.shape.borderRadius as number) * 3}px`,
+
+ width: DRAWER_WIDTH,
+ overflowX: "visible",
+ overflowY: "visible",
+
+ top: APP_BAR_HEIGHT + TABLE_HEADER_HEIGHT,
+ height: `calc(100% - ${APP_BAR_HEIGHT + TABLE_HEADER_HEIGHT}px)`,
+
+ transition: theme.transitions.create("transform", {
+ easing: theme.transitions.easing.easeInOut,
+ duration: theme.transitions.duration.standard,
+ }),
+
+ zIndex: theme.zIndex.drawer - 1,
+ },
+ paperClose: {
+ transform: `translateX(${DRAWER_WIDTH - DRAWER_COLLAPSED_WIDTH}px)`,
+ },
+
+ "@keyframes bumpPaper": {
+ "0%": {
+ transform: `translateX(${DRAWER_WIDTH - DRAWER_COLLAPSED_WIDTH}px)`,
+ },
+ "50%": {
+ transform: `translateX(calc(${
+ DRAWER_WIDTH - DRAWER_COLLAPSED_WIDTH
+ }px - ${theme.spacing(4)}))`,
+ },
+ "100%": {
+ transform: `translateX(${DRAWER_WIDTH - DRAWER_COLLAPSED_WIDTH}px)`,
+ },
+ },
+ bumpPaper: {
+ animation: `${theme.transitions.duration.standard}ms ${theme.transitions.easing.easeInOut} $bumpPaper`,
+ },
+
+ fab: {
+ display: "flex",
+
+ boxShadow: theme.shadows[4],
+ "&:active": { boxShadow: theme.shadows[4] },
+
+ "&.Mui-disabled": { boxShadow: theme.shadows[4] },
+
+ "& + &": { marginTop: theme.spacing(4) },
+ },
+
+ navFabContainer: {
+ position: "absolute",
+ top: theme.spacing(6),
+ left: -18,
+ zIndex: theme.zIndex.drawer + 1,
+ },
+ "@keyframes navFab": {
+ from: {
+ opacity: 0,
+ transform: "translateY(-48px)",
+ },
+ to: {
+ opacity: 1,
+ transform: "translateY(0)",
+ },
+ },
+ navFab: {
+ animation: `${theme.transitions.duration.standard}ms ${theme.transitions.easing.easeInOut} both $navFab`,
+ },
+
+ drawerFabContainer: {
+ position: "absolute",
+ top: "50%",
+ transform: "translateY(-50%)",
+ left: theme.spacing(-3.5),
+ zIndex: theme.zIndex.drawer + 1,
+ },
+ drawerFabIcon: {
+ // width: "2em",
+ // height: "2em",
+ "$open &": { transform: "rotate(180deg)" },
+ },
+
+ drawerContents: {
+ padding: theme.spacing(5),
+ overflowY: "auto",
+ },
+ })
+);
diff --git a/src/components/Snack.tsx b/src/components/Snack.tsx
new file mode 100644
index 000000000..76b15c7eb
--- /dev/null
+++ b/src/components/Snack.tsx
@@ -0,0 +1,101 @@
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { Snackbar, CircularProgress } from "@material-ui/core";
+import Alert from "@material-ui/core/Alert";
+
+import { useSnackContext } from "contexts/SnackContext";
+import antlerPalette from "theme/palette";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ progressAction: { marginRight: 0 },
+ progressText: { marginLeft: theme.spacing(2) },
+ progress: {
+ color: antlerPalette.green[100],
+ marginLeft: theme.spacing(2),
+ },
+
+ alertIcon: { padding: 0 },
+ alertMessage: { padding: theme.spacing(0.75, 2) },
+ })
+);
+
+export default function Snack() {
+ const classes = useStyles();
+
+ const {
+ position,
+ isOpen,
+ close,
+ message,
+ duration,
+ action,
+ variant,
+ progress,
+ } = useSnackContext();
+
+ if (variant === "progress")
+ return (
+
+
+ {progress.value}
+ {progress.target && `/${progress.target}`}
+
+
+
+ >
+ }
+ ContentProps={{ classes: { action: classes.progressAction } }}
+ // Stop closing when user clicks
+ ClickAwayListenerProps={{ mouseEvent: false }}
+ />
+ );
+
+ if (!variant)
+ return (
+
+ );
+
+ return (
+
+
+ {message}
+
+
+ );
+}
diff --git a/src/components/StyledCard.tsx b/src/components/StyledCard.tsx
new file mode 100644
index 000000000..f29a66009
--- /dev/null
+++ b/src/components/StyledCard.tsx
@@ -0,0 +1,181 @@
+import clsx from "clsx";
+import { Link, LinkProps } from "react-router-dom";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import {
+ Card,
+ Grid,
+ Typography,
+ Button,
+ CardActions,
+ CardContent,
+ CardMedia,
+ Divider,
+} from "@material-ui/core";
+import { ButtonProps } from "@material-ui/core/Button";
+
+import GoIcon from "assets/icons/Go";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: { width: "100%" },
+ container: { height: "100%" },
+ cardContent: { "&:last-child": { paddingBottom: 0 } },
+
+ headerSection: { marginBottom: theme.spacing(1) },
+ overline: {
+ marginBottom: theme.spacing(2),
+ color: theme.palette.text.secondary,
+ },
+ title: { whiteSpace: "pre-line" },
+ image: {
+ width: 80,
+ height: 80,
+ borderRadius: theme.shape.borderRadius,
+ },
+
+ cardActions: {
+ // padding: theme.spacing(1),
+
+ display: "flex",
+ justifyContent: "space-between",
+ },
+
+ divider: {
+ margin: theme.spacing(2),
+ marginBottom: 0,
+ },
+ })
+);
+
+interface StyledCardProps {
+ className?: string;
+
+ overline?: React.ReactNode;
+ title?: string;
+ imageSource?: string;
+
+ bodyContent?: React.ReactNode;
+
+ primaryButton?: Partial;
+ primaryLink?: {
+ to: LinkProps["to"];
+ children?: React.ReactNode;
+ label?: string;
+ };
+ secondaryAction?: React.ReactNode;
+ headerAction?: React.ReactNode;
+}
+
+export default function StyledCard({
+ className,
+ overline,
+ title,
+ imageSource,
+ bodyContent,
+ primaryButton,
+ primaryLink,
+ secondaryAction,
+ headerAction,
+}: StyledCardProps) {
+ const classes = useStyles();
+
+ return (
+
+
+
+
+
+
+
+
+ {overline && (
+
+ {overline}
+
+ )}
+
+ {title && (
+
+ {title}
+
+ )}
+ {headerAction && headerAction}
+
+
+
+ {imageSource && (
+
+
+
+ )}
+
+
+
+
+ {bodyContent && Array.isArray(bodyContent) ? (
+
+ {bodyContent.map((element) => (
+ {element}
+ ))}
+
+ ) : (
+
+ {bodyContent}
+
+ )}
+
+
+
+
+
+
+
+
+ {primaryButton && (
+
+ )}
+ {primaryLink && (
+ }
+ />
+ )}
+
+ {secondaryAction}
+
+
+
+
+ );
+}
diff --git a/src/components/Table/BulkActions/index.tsx b/src/components/Table/BulkActions/index.tsx
new file mode 100644
index 000000000..f37da8559
--- /dev/null
+++ b/src/components/Table/BulkActions/index.tsx
@@ -0,0 +1,308 @@
+import { useState } from "react";
+import _find from "lodash/find";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import {
+ alpha,
+ Grow,
+ Paper,
+ Grid,
+ Tooltip,
+ IconButton,
+ Typography,
+ TextField,
+ MenuItem,
+} from "@material-ui/core";
+
+import CopyCellsIcon from "assets/icons/CopyCells";
+import ClearSelectionIcon from "@material-ui/icons/IndeterminateCheckBox";
+import DeleteIcon from "@material-ui/icons/DeleteForever";
+import ArrowDropUpIcon from "@material-ui/icons/ArrowDropUp";
+
+import { useConfirmation } from "components/ConfirmationDialog/Context";
+import { useRowyContext } from "contexts/RowyContext";
+import { useSnackContext } from "contexts/SnackContext";
+import { formatPath } from "utils/fns";
+import { cloudFunction } from "firebase/callables";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: {
+ position: "fixed",
+ bottom: theme.spacing(2),
+ left: "50%",
+ transform: "translateX(-50%)",
+ },
+
+ paper: {
+ height: 64,
+ borderRadius: 32,
+ padding: theme.spacing(0, 1),
+ [theme.breakpoints.up("lg")]: { paddingRight: theme.spacing(2) },
+
+ zIndex: theme.zIndex.modal,
+
+ backgroundColor: theme.palette.background.default,
+
+ width: 470,
+ maxWidth: "100vw",
+ overflowX: "auto",
+ },
+
+ grid: {
+ height: "100%",
+ marginTop: 0,
+ marginBottom: 0,
+ },
+ spacer: { width: theme.spacing(2) },
+
+ selectedContainer: {
+ flexBasis: 206,
+ flexShrink: 0,
+ },
+ selected: {
+ color: theme.palette.text.disabled,
+ fontFeatureSettings: '"tnum"',
+ userSelect: "none",
+
+ display: "inline-block",
+ marginRight: theme.spacing(1),
+ minWidth: 150,
+ },
+
+ dropdown: {
+ minWidth: 120,
+ margin: 0,
+ },
+ inputBaseRoot: {
+ borderRadius: theme.shape.borderRadius,
+ backgroundColor:
+ theme.palette.mode === "dark"
+ ? alpha(theme.palette.text.primary, 0.06)
+ : undefined,
+ },
+ dropdownLabel: {
+ left: theme.spacing(1.5),
+ top: "50%",
+ transform: "translateY(-50%) !important",
+
+ ...theme.typography.body1,
+ },
+ dropdownLabelFocused: {
+ "$dropdownLabel&": { color: theme.palette.text.primary },
+ },
+ select: {
+ paddingTop: "6px !important",
+ paddingBottom: "7px !important",
+ },
+ dropdownMenu: { marginTop: theme.spacing(-3) },
+ })
+);
+
+export default function BulkActions({ selectedRows, columns, clearSelection }) {
+ const classes = useStyles();
+ const [, setLoading] = useState();
+ const { tableActions, tableState } = useRowyContext();
+
+ const { requestConfirmation } = useConfirmation();
+ const snack = useSnackContext();
+
+ const actionColumns: { name: string; key: string; config: any }[] = columns
+ .filter((column) => column.type === "ACTION")
+ .map((column) => ({
+ name: column.name,
+ key: column.key,
+ config: column.config,
+ }));
+
+ const handleDuplicate = () => {
+ selectedRows.forEach((row) => {
+ const clonedRow = { ...row };
+ // remove metadata
+ delete clonedRow.ref;
+ delete clonedRow.rowHeight;
+ delete clonedRow._updatedAt;
+ delete clonedRow._updatedBy;
+ delete clonedRow._createdAt;
+ Object.keys(clonedRow).forEach((key) => {
+ if (clonedRow[key] === undefined) {
+ delete clonedRow[key];
+ }
+ });
+ if (tableActions) tableActions?.row.add(clonedRow);
+ });
+ clearSelection();
+ };
+ const handleDelete = () => {
+ selectedRows.forEach((row) => row.ref.delete());
+ clearSelection();
+ };
+
+ const executeAction = async (key: string, actionType: string) => {
+ const actionColumn = _find(actionColumns, { key });
+ if (!actionColumn) return;
+
+ console.log({ actionColumn, selectedRows, actionType });
+ const callableName = actionColumn.config.callableName ?? "actionScript";
+
+ const calls = selectedRows.map((row) => {
+ const { ref } = row;
+ const data = {
+ ref: {
+ path: ref.path,
+ id: ref.id,
+ tablePath: window.location.pathname,
+ },
+ column: actionColumn,
+ action: actionType,
+ schemaDocPath: formatPath(tableState?.tablePath ?? ""),
+ actionParams: {},
+ };
+ return cloudFunction(
+ callableName,
+ data,
+ async (response) => {
+ const { message, cellValue, success } = response.data;
+ // setIsRunning(false);
+ snack.open({
+ message: JSON.stringify(message),
+ variant: success ? "success" : "error",
+ });
+ if (cellValue && cellValue.status) {
+ return ref.update({ [actionColumn.key]: cellValue });
+ }
+ },
+ (error) => {
+ console.error("ERROR", callableName, error);
+ //setIsRunning(false);
+ snack.open({ message: JSON.stringify(error), variant: "error" });
+ }
+ );
+ });
+ setLoading(true);
+ const result = await Promise.all(calls);
+ await Promise.all(result);
+ console.log(result);
+ setLoading(false);
+ clearSelection();
+ };
+
+ const numSelected = selectedRows.length;
+
+ return (
+
+
0}>
+
+
+
+
+
+
+
+
+
+
+ {numSelected} row{numSelected !== 1 && "s"} selected
+
+
+
+
+
+
+ executeAction(event.target.value, "run")}
+ margin="dense"
+ InputProps={{
+ disableUnderline: true,
+ classes: { root: classes.inputBaseRoot },
+ }}
+ InputLabelProps={{
+ classes: {
+ root: classes.dropdownLabel,
+ focused: classes.dropdownLabelFocused,
+ },
+ }}
+ SelectProps={{
+ classes: { root: classes.select },
+ displayEmpty: true,
+ MenuProps: {
+ anchorOrigin: { vertical: "top", horizontal: "left" },
+ transformOrigin: { vertical: "bottom", horizontal: "left" },
+ classes: { paper: classes.dropdownMenu },
+ },
+ IconComponent: ArrowDropUpIcon,
+ }}
+ label={`${actionColumns.length} action${
+ actionColumns.length !== 1 ? "s" : ""
+ }`}
+ >
+ {actionColumns.map((action) => (
+
+ {action.name}
+
+ ))}
+
+
+
+
+
+
+
+ {
+ requestConfirmation({
+ title: "Duplicate Rows?",
+ body: `Are you sure you want to duplicate the ${numSelected} selected row${
+ numSelected !== 1 ? "s" : ""
+ }?`,
+ confirm: "Duplicate Rows",
+ handleConfirm: handleDuplicate,
+ });
+ }}
+ aria-label="Duplicate selected rows"
+ >
+
+
+
+
+
+
+
+ {
+ requestConfirmation({
+ title: "Delete Rows?",
+ body: `Are you sure you want to delete the ${numSelected} select row${
+ numSelected !== 1 ? "s" : ""
+ }?`,
+ confirm: "Delete Rows",
+ handleConfirm: handleDelete,
+ });
+ }}
+ aria-label="Delete selected rows"
+ >
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/components/Table/CellValidation.tsx b/src/components/Table/CellValidation.tsx
new file mode 100644
index 000000000..a4e602065
--- /dev/null
+++ b/src/components/Table/CellValidation.tsx
@@ -0,0 +1,115 @@
+import clsx from "clsx";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import RichTooltip from "components/RichTooltip";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: {
+ "&&": {
+ position: "absolute",
+ top: 0,
+ right: 0,
+ bottom: 0,
+ left: 0,
+ padding: "var(--cell-padding)",
+
+ overflow: "hidden",
+ contain: "strict",
+ display: "flex",
+ alignItems: "center",
+ },
+ },
+
+ isInvalid: {
+ boxShadow: `inset 0 0 0 2px ${theme.palette.error.main}`,
+ },
+
+ dot: {
+ position: "absolute",
+ right: -5,
+ top: "50%",
+ transform: "translateY(-50%)",
+ zIndex: 1,
+
+ width: 12,
+ height: 12,
+
+ borderRadius: "50%",
+ backgroundColor: theme.palette.error.main,
+ },
+ })
+);
+
+export interface ICellValidationProps
+ extends React.DetailedHTMLProps<
+ React.HTMLAttributes,
+ HTMLDivElement
+ > {
+ value: any;
+ required?: boolean;
+ validationRegex?: string;
+}
+
+export default function CellValidation({
+ value,
+ required,
+ validationRegex,
+
+ className,
+ children,
+ ...props
+}: ICellValidationProps) {
+ const classes = useStyles();
+
+ const isInvalid = validationRegex && !new RegExp(validationRegex).test(value);
+ const isMissing = required && value === undefined;
+
+ if (isInvalid)
+ return (
+ <>
+ (
+
+ )}
+ />
+
+
+ {children}
+
+ >
+ );
+
+ if (isMissing)
+ return (
+ <>
+ (
+
+ )}
+ />
+
+
+ {children}
+
+ >
+ );
+
+ return (
+
+ {children}
+
+ );
+}
diff --git a/src/components/Table/ColumnHeader.tsx b/src/components/Table/ColumnHeader.tsx
new file mode 100644
index 000000000..9551cd059
--- /dev/null
+++ b/src/components/Table/ColumnHeader.tsx
@@ -0,0 +1,321 @@
+import { useRef } from "react";
+import clsx from "clsx";
+import { HeaderRendererProps } from "react-data-grid";
+import { useDrag, useDrop, DragObjectWithType } from "react-dnd";
+import { useCombinedRefs } from "react-data-grid/lib/hooks";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import {
+ alpha,
+ Tooltip,
+ Fade,
+ Grid,
+ IconButton,
+ Typography,
+} from "@material-ui/core";
+import SortDescIcon from "@material-ui/icons/ArrowDownward";
+import DropdownIcon from "@material-ui/icons/MoreHoriz";
+import LockIcon from "@material-ui/icons/Lock";
+
+import { FieldType } from "constants/fields";
+import { getFieldProp } from "components/fields";
+import { useRowyContext } from "contexts/RowyContext";
+import { RowyOrderBy } from "hooks/useRowy";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: {
+ height: "100%",
+ "& svg, & button": { display: "block" },
+
+ color: theme.palette.text.secondary,
+ transition: theme.transitions.create("color", {
+ duration: theme.transitions.duration.short,
+ }),
+ "&:hover": { color: theme.palette.text.primary },
+
+ cursor: "move",
+
+ margin: theme.spacing(0, -1.5),
+ padding: theme.spacing(0, 0.5, 0, 1.5),
+ width: `calc(100% + ${theme.spacing(1.5 * 2)})`,
+ },
+ isDragging: { opacity: 0.5 },
+ isOver: {
+ backgroundColor: alpha(
+ theme.palette.primary.main,
+ theme.palette.action.focusOpacity
+ ),
+ color: theme.palette.primary.main,
+ },
+
+ columnNameContainer: {
+ flexShrink: 1,
+ overflow: "hidden",
+ margin: theme.spacing(0, 0.5),
+ marginRight: -30,
+ },
+ columnName: {
+ ...theme.typography.caption,
+ fontWeight: theme.typography.fontWeightMedium,
+ lineHeight: "44px",
+ textOverflow: "clip",
+ },
+
+ columnNameTooltip: {
+ background: theme.palette.background.default,
+ color: theme.palette.text.primary,
+
+ margin: "-43px 0 0 !important",
+ padding: theme.spacing(0, 1.5, 0, 0),
+
+ "& *": { lineHeight: "42px" },
+ },
+
+ sortIconContainer: {
+ backgroundColor: theme.palette.background.default,
+ // width: 30,
+ // height: 30,
+
+ opacity: 0,
+ transition: theme.transitions.create("opacity", {
+ duration: theme.transitions.duration.shortest,
+ }),
+ "$root:hover &": { opacity: 1 },
+ },
+ sortIconContainerSorted: { opacity: 1 },
+
+ sortIcon: {
+ transition: theme.transitions.create(["background-color", "transform"], {
+ duration: theme.transitions.duration.short,
+ }),
+ },
+ sortIconAsc: {
+ transform: "rotate(180deg)",
+ },
+
+ dropdownButton: {
+ transition: theme.transitions.create("color", {
+ duration: theme.transitions.duration.short,
+ }),
+
+ color: theme.palette.text.disabled,
+ "$root:hover &": { color: theme.palette.text.primary },
+ },
+ })
+);
+
+interface ColumnDragObject extends DragObjectWithType {
+ key: string;
+}
+
+export default function DraggableHeaderRenderer({
+ column,
+}: HeaderRendererProps & {
+ onColumnsReorder: (sourceKey: string, targetKey: string) => void;
+}) {
+ const classes = useStyles();
+
+ const {
+ tableState,
+ tableActions,
+ userClaims,
+ columnMenuRef,
+ } = useRowyContext();
+ const [{ isDragging }, drag] = useDrag({
+ item: { key: column.key, type: "COLUMN_DRAG" },
+ collect: (monitor) => ({
+ isDragging: !!monitor.isDragging(),
+ }),
+ });
+
+ const [{ isOver }, drop] = useDrop({
+ accept: "COLUMN_DRAG",
+ drop({ key, type }: ColumnDragObject) {
+ if (type === "COLUMN_DRAG") {
+ // onColumnsReorder(key, props.column.key);
+ tableActions?.column.reorder(key, column.key);
+ }
+ },
+ collect: (monitor) => ({
+ isOver: !!monitor.isOver(),
+ canDrop: !!monitor.canDrop(),
+ }),
+ });
+
+ const headerRef = useCombinedRefs(drag, drop);
+ const buttonRef = useRef(null);
+
+ if (!columnMenuRef || !tableState || !tableActions) return null;
+ const { orderBy } = tableState;
+
+ const handleOpenMenu = (e: React.MouseEvent) => {
+ e.preventDefault();
+ columnMenuRef?.current?.setSelectedColumnHeader({
+ column,
+ anchorEl: buttonRef.current,
+ });
+ };
+
+ const isSorted = orderBy?.[0]?.key === (column.key as string);
+ const isAsc = isSorted && orderBy?.[0]?.direction === "asc";
+
+ const handleSortClick = () => {
+ if (isAsc) {
+ const ordering: RowyOrderBy = [
+ { key: column.key as string, direction: "desc" },
+ ];
+
+ tableActions.table.orderBy(ordering);
+ } else {
+ const ordering: RowyOrderBy = [
+ { key: column.key as string, direction: "asc" },
+ ];
+ tableActions.table.orderBy(ordering);
+ }
+ };
+
+ return (
+
+
+ Click to copy field key:
+
+ {column.key as string}
+
+ >
+ }
+ enterDelay={1000}
+ placement="bottom-start"
+ >
+ {
+ navigator.clipboard.writeText(column.key as string);
+ }}
+ >
+ {column.editable === false ? (
+
+ ) : (
+ getFieldProp("icon", (column as any).type)
+ )}
+
+
+
+
+
+ {column.name}
+
+ }
+ enterDelay={1000}
+ placement="bottom-start"
+ disableInteractive
+ // PopperProps={{
+ // modifiers: [
+ // {
+ // name: "flip",
+ // options: {
+ // enabled: false,
+ // },
+ // },
+ // {
+ // name: "preventOverflow",
+ // options: {
+ // enabled: false,
+ // boundariesElement: "scrollParent",
+ // },
+ // },
+ // {
+ // name: "hide",
+ // options: {
+ // enabled: false,
+ // },
+ // },
+ // ],
+ // }}
+ TransitionComponent={Fade}
+ classes={{ tooltip: classes.columnNameTooltip }}
+ >
+
+ {column.name}
+
+
+
+
+ {(column as any).type !== FieldType.id && (
+
+
+
+
+
+ )}
+
+ {(userClaims?.roles?.includes("ADMIN") ||
+ (userClaims?.roles?.includes("OPS") &&
+ [FieldType.multiSelect, FieldType.singleSelect].includes(
+ (column as any).type
+ ))) && (
+
+
+
+
+
+ )}
+
+ );
+ // return (
+ //
+ // {props.column.name}
+ //
+ // );
+}
diff --git a/src/components/Table/ColumnMenu/FieldSettings/DefaultValueInput.tsx b/src/components/Table/ColumnMenu/FieldSettings/DefaultValueInput.tsx
new file mode 100644
index 000000000..bc00947f2
--- /dev/null
+++ b/src/components/Table/ColumnMenu/FieldSettings/DefaultValueInput.tsx
@@ -0,0 +1,176 @@
+import React from "react";
+import { useForm } from "react-hook-form";
+import { IMenuModalProps } from "..";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import Switch from "@material-ui/core/Switch";
+import FormControlLabel from "@material-ui/core/FormControlLabel";
+import {
+ Typography,
+ TextField,
+ MenuItem,
+ ListItemText,
+} from "@material-ui/core";
+import Subheading from "../Subheading";
+
+import { getFieldProp } from "components/fields";
+import CodeEditorHelper from "components/CodeEditorHelper";
+import CodeEditor from "components/Table/editors/CodeEditor";
+import FormAutosave from "./FormAutosave";
+import { FieldType } from "constants/fields";
+import WIKI_LINKS from "constants/wikiLinks";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ typeSelect: { marginBottom: theme.spacing(1) },
+ typeSelectItem: { whiteSpace: "normal" },
+
+ codeEditorContainer: {
+ border: `1px solid ${theme.palette.divider}`,
+ borderRadius: theme.shape.borderRadius,
+ },
+
+ mono: {
+ fontFamily: theme.typography.fontFamilyMono,
+ },
+ })
+);
+
+export interface IDefaultValueInputProps extends IMenuModalProps {
+ handleChange: (key: any) => (update: any) => void;
+}
+
+export default function DefaultValueInput({
+ config,
+ handleChange,
+ type,
+ fieldName,
+ ...props
+}: IDefaultValueInputProps) {
+ const classes = useStyles();
+ const _type =
+ type !== FieldType.derivative
+ ? type
+ : config.renderFieldType ?? FieldType.shortText;
+ const customFieldInput = getFieldProp("SideDrawerField", _type);
+ const { control } = useForm({
+ mode: "onBlur",
+ defaultValues: {
+ [fieldName]:
+ config.defaultValue?.value ?? getFieldProp("initialValue", _type),
+ },
+ });
+ console.log(config);
+ return (
+ <>
+ Default Value
+
+ The default value will be the initial value of this cell when a new row
+ is added.
+
+
+ handleChange("defaultValue.type")(e.target.value)}
+ fullWidth
+ className={classes.typeSelect}
+ >
+
+
+
+
+
+ Initialise as null .
+ >
+ }
+ className={classes.typeSelectItem}
+ />
+
+
+
+
+
+
+
+
+ {(!config.defaultValue || config.defaultValue.type === "undefined") && (
+ <>
+ handleChange("required")(checked)}
+ name="required"
+ />
+ }
+ style={{
+ marginLeft: 0,
+ justifyContent: "space-between",
+ }}
+ />
+ {
+
+ The row will not be created or updated unless all required values
+ are set.
+
+ }
+ >
+ )}
+ {config.defaultValue?.type === "static" && customFieldInput && (
+
+ )}
+
+ {config.defaultValue?.type === "dynamic" && (
+ <>
+
+
+
+
+ >
+ )}
+ >
+ );
+}
diff --git a/www/src/components/Table/ColumnMenu/FieldSettings/FormAutosave.tsx b/src/components/Table/ColumnMenu/FieldSettings/FormAutosave.tsx
similarity index 51%
rename from www/src/components/Table/ColumnMenu/FieldSettings/FormAutosave.tsx
rename to src/components/Table/ColumnMenu/FieldSettings/FormAutosave.tsx
index 5ae4646f5..79c841e09 100644
--- a/www/src/components/Table/ColumnMenu/FieldSettings/FormAutosave.tsx
+++ b/src/components/Table/ColumnMenu/FieldSettings/FormAutosave.tsx
@@ -5,20 +5,20 @@ import _isEqual from "lodash/isEqual";
import { Control, useWatch } from "react-hook-form";
export interface IAutosaveProps {
- control: Control;
- handleSave: (values: any) => void;
+ control: Control;
+ handleSave: (values: any) => void;
}
export default function FormAutosave({ control, handleSave }: IAutosaveProps) {
- const values = useWatch({ control });
+ const values = useWatch({ control });
- const [debouncedValue] = useDebounce(values, 1000, {
- equalityFn: _isEqual,
- });
+ const [debouncedValue] = useDebounce(values, 1000, {
+ equalityFn: _isEqual,
+ });
- useEffect(() => {
- handleSave(debouncedValue);
- }, [debouncedValue]);
+ useEffect(() => {
+ handleSave(debouncedValue);
+ }, [debouncedValue]);
- return null;
+ return null;
}
diff --git a/src/components/Table/ColumnMenu/FieldSettings/index.tsx b/src/components/Table/ColumnMenu/FieldSettings/index.tsx
new file mode 100644
index 000000000..3af2e39ab
--- /dev/null
+++ b/src/components/Table/ColumnMenu/FieldSettings/index.tsx
@@ -0,0 +1,186 @@
+import React, { useState, Suspense, useMemo } from "react";
+
+import _set from "lodash/set";
+import { IMenuModalProps } from "..";
+
+import Modal from "components/Modal";
+import { getFieldProp } from "components/fields";
+import DefaultValueInput from "./DefaultValueInput";
+import ErrorBoundary from "components/ErrorBoundary";
+import Loading from "components/Loading";
+
+import { useRowyContext } from "contexts/RowyContext";
+import { useSnackContext } from "contexts/SnackContext";
+import { useSnackLogContext } from "contexts/SnackLogContext";
+import { db } from "../../../../firebase";
+import { useAppContext } from "contexts/AppContext";
+import { useConfirmation } from "components/ConfirmationDialog";
+import { FieldType } from "constants/fields";
+
+import Typography from "@material-ui/core/Typography";
+import Divider from "@material-ui/core/Divider";
+import Subheading from "components/Table/ColumnMenu/Subheading";
+import Button from "@material-ui/core/Button";
+import routes from "constants/routes";
+export default function FieldSettings(props: IMenuModalProps) {
+ const {
+ name,
+ fieldName,
+ type,
+ open,
+ config,
+ handleClose,
+ handleSave,
+ } = props;
+
+ const [showRebuildPrompt, setShowRebuildPrompt] = useState(false);
+ const [newConfig, setNewConfig] = useState(config ?? {});
+ const customFieldSettings = getFieldProp("settings", type);
+ const initializable = getFieldProp("initializable", type);
+
+ const { requestConfirmation } = useConfirmation();
+ const { tableState } = useRowyContext();
+ const snack = useSnackContext();
+ const snackLog = useSnackLogContext();
+ const appContext = useAppContext();
+
+ const handleChange = (key: string) => (update: any) => {
+ if (
+ showRebuildPrompt === false &&
+ (key.includes("defaultValue") || type === FieldType.derivative) &&
+ config[key] !== update
+ ) {
+ setShowRebuildPrompt(true);
+ }
+ console.log(key, update);
+ const updatedConfig = _set({ ...newConfig }, key, update);
+ setNewConfig(updatedConfig);
+ };
+ const rendedFieldSettings = useMemo(
+ () =>
+ [FieldType.derivative, FieldType.aggregate].includes(type) &&
+ newConfig.renderFieldType
+ ? getFieldProp("settings", newConfig.renderFieldType)
+ : null,
+ [newConfig.renderFieldType, type]
+ );
+ if (!open) return null;
+ console.log(newConfig);
+ return (
+ }>
+ <>
+ {initializable && (
+ <>
+
+ {/* top margin fixes visual bug */}
+
+
+
+
+ >
+ )}
+
+
+ {customFieldSettings &&
+ React.createElement(customFieldSettings, {
+ config: newConfig,
+ handleChange,
+ })}
+
+ {rendedFieldSettings && (
+
+
+
+ {" "}
+ Rendered field config
+
+ {React.createElement(rendedFieldSettings, {
+ config: newConfig,
+ handleChange,
+ })}
+
+ )}
+ {/* {
+
+ } */}
+ >
+
+ }
+ actions={{
+ primary: {
+ onClick: () => {
+ if (showRebuildPrompt) {
+ requestConfirmation({
+ title: "Deploy Changes",
+ body:
+ "You have made changes that affect the behavior of the cloud function of this table, Would you like to redeploy it now?",
+ confirm: "Deploy",
+ cancel: "Later",
+ handleConfirm: async () => {
+ const settingsDoc = await db.doc("/_rowy_/settings").get();
+ const buildUrl = settingsDoc.get("buildUrl");
+ if (!buildUrl) {
+ snack.open({
+ message: `Rowy functions builder is not yet setup`,
+ variant: "error",
+ action: (
+
+ Go to Settings
+
+ ),
+ });
+ }
+ const userTokenInfo = await appContext?.currentUser?.getIdTokenResult();
+ const userToken = userTokenInfo?.token;
+ try {
+ snackLog.requestSnackLog();
+ const response = await fetch(buildUrl, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({
+ configPath: tableState?.config.tableConfig.path,
+ token: userToken,
+ }),
+ });
+ const data = await response.json();
+ } catch (e) {
+ console.error(e);
+ }
+ },
+ });
+ }
+ handleSave(fieldName, { config: newConfig });
+ handleClose();
+ setShowRebuildPrompt(false);
+ },
+ children: "Update",
+ },
+ secondary: {
+ onClick: handleClose,
+ children: "Cancel",
+ },
+ }}
+ />
+ );
+}
diff --git a/src/components/Table/ColumnMenu/FieldsDropdown.tsx b/src/components/Table/ColumnMenu/FieldsDropdown.tsx
new file mode 100644
index 000000000..0dec25cc7
--- /dev/null
+++ b/src/components/Table/ColumnMenu/FieldsDropdown.tsx
@@ -0,0 +1,80 @@
+import { makeStyles, createStyles } from "@material-ui/styles";
+import {
+ TextField,
+ MenuItem,
+ ListItemIcon,
+ TextFieldProps,
+} from "@material-ui/core";
+
+import { FIELDS } from "components/fields";
+import { FieldType } from "constants/fields";
+import { getFieldProp } from "components/fields";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ helperText: {
+ ...theme.typography.body2,
+ marginTop: theme.spacing(1),
+ },
+
+ listItemIcon: {
+ verticalAlign: "text-bottom",
+ minWidth: theme.spacing(5),
+ "& svg": { margin: theme.spacing(-0.5, 0) },
+ },
+ })
+);
+
+export interface IFieldsDropdownProps {
+ value: FieldType;
+ onChange: TextFieldProps["onChange"];
+ className?: string;
+ hideLabel?: boolean;
+ options?: FieldType[];
+}
+
+/**
+ * Returns dropdown component of all available types
+ */
+export default function FieldsDropdown({
+ value,
+ onChange,
+ className,
+ hideLabel = false,
+ options: optionsProp,
+}: IFieldsDropdownProps) {
+ const classes = useStyles();
+
+ const options = optionsProp
+ ? FIELDS.filter((fieldConfig) => optionsProp.indexOf(fieldConfig.type) > -1)
+ : FIELDS;
+
+ return (
+
+ {options.map((fieldConfig) => (
+
+
+ {fieldConfig.icon}
+
+ {fieldConfig.name}
+
+ ))}
+
+ );
+}
diff --git a/src/components/Table/ColumnMenu/MenuContents.tsx b/src/components/Table/ColumnMenu/MenuContents.tsx
new file mode 100644
index 000000000..ea68036bd
--- /dev/null
+++ b/src/components/Table/ColumnMenu/MenuContents.tsx
@@ -0,0 +1,82 @@
+import {
+ MenuItem,
+ ListItemIcon,
+ ListSubheader,
+ Divider,
+} from "@material-ui/core";
+import { alpha } from "@material-ui/core/styles";
+
+export interface IMenuContentsProps {
+ menuItems: {
+ type?: string;
+ label?: string;
+ activeLabel?: string;
+ icon?: JSX.Element;
+ activeIcon?: JSX.Element;
+ onClick?: () => void;
+ active?: boolean;
+ color?: "error";
+ disabled?: boolean;
+ }[];
+}
+
+export default function MenuContents({ menuItems }: IMenuContentsProps) {
+ return (
+ <>
+ {menuItems.map((item, index) => {
+ if (item.type === "subheader")
+ return (
+ <>
+ {index !== 0 && }
+
+ {item.label}
+
+ >
+ );
+
+ let icon: JSX.Element = item.icon ?? <>>;
+ if (item.active && !!item.activeIcon) icon = item.activeIcon;
+
+ return (
+
+ alpha(
+ theme.palette.error.main,
+ theme.palette.action.hoverOpacity
+ ),
+ },
+ }
+ : undefined
+ }
+ selected={item.active}
+ disabled={item.disabled}
+ >
+
+ alpha(
+ theme.palette.error.main,
+ theme.palette.action.activeOpacity
+ ),
+ }
+ : undefined
+ }
+ >
+ {icon}
+
+ {item.active ? item.activeLabel : item.label}
+
+ );
+ })}
+ >
+ );
+}
diff --git a/src/components/Table/ColumnMenu/NameChange.tsx b/src/components/Table/ColumnMenu/NameChange.tsx
new file mode 100644
index 000000000..355ea736e
--- /dev/null
+++ b/src/components/Table/ColumnMenu/NameChange.tsx
@@ -0,0 +1,53 @@
+import { useState } from "react";
+import { IMenuModalProps } from ".";
+
+import { TextField } from "@material-ui/core";
+
+import Modal from "components/Modal";
+
+export default function NameChange({
+ name,
+ fieldName,
+ open,
+ handleClose,
+ handleSave,
+}: IMenuModalProps) {
+ const [newName, setName] = useState(name);
+
+ if (!open) return null;
+
+ return (
+ {
+ setName(e.target.value);
+ }}
+ />
+ }
+ actions={{
+ primary: {
+ onClick: () => {
+ handleSave(fieldName, { name: newName });
+ handleClose();
+ },
+ children: "Update",
+ },
+ secondary: {
+ onClick: handleClose,
+ children: "Cancel",
+ },
+ }}
+ />
+ );
+}
diff --git a/src/components/Table/ColumnMenu/NewColumn.tsx b/src/components/Table/ColumnMenu/NewColumn.tsx
new file mode 100644
index 000000000..eb8976ef6
--- /dev/null
+++ b/src/components/Table/ColumnMenu/NewColumn.tsx
@@ -0,0 +1,134 @@
+import { useState, useEffect } from "react";
+import _camel from "lodash/camelCase";
+import { IMenuModalProps } from ".";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { TextField } from "@material-ui/core";
+
+import Modal from "components/Modal";
+import { FieldType } from "constants/fields";
+import FieldsDropdown from "./FieldsDropdown";
+import { getFieldProp } from "components/fields";
+import { analytics } from "analytics";
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ helperText: {
+ ...theme.typography.body2,
+ marginTop: theme.spacing(1),
+ },
+ })
+);
+
+export interface IFormDialogProps extends IMenuModalProps {
+ data: Record;
+ openSettings: (column: any) => void;
+}
+
+export default function FormDialog({
+ open,
+ data,
+ openSettings,
+ handleClose,
+ handleSave,
+}: IFormDialogProps) {
+ const classes = useStyles();
+
+ const [columnLabel, setColumnLabel] = useState("");
+ const [fieldKey, setFieldKey] = useState("");
+ const [type, setType] = useState(FieldType.shortText);
+ const requireConfiguration = getFieldProp("requireConfiguration", type);
+ useEffect(() => {
+ if (type !== FieldType.id) setFieldKey(_camel(columnLabel));
+ }, [columnLabel]);
+
+ useEffect(() => {
+ if (type === FieldType.id) {
+ setColumnLabel("ID");
+ setFieldKey("id");
+ }
+ }, [type]);
+
+ if (!open) return null;
+
+ return (
+
+
+ setColumnLabel(e.target.value)}
+ helperText="Set the user-facing name for this column."
+ FormHelperTextProps={{ classes: { root: classes.helperText } }}
+ />
+
+
+
+ setFieldKey(e.target.value)}
+ disabled={type === FieldType.id && fieldKey === "id"}
+ helperText="Set the Firestore field key to link to this column. It will display any existing data for this field key."
+ FormHelperTextProps={{ classes: { root: classes.helperText } }}
+ />
+
+
+
+ setType(newType.target.value as FieldType)}
+ />
+
+ >
+ }
+ actions={{
+ primary: {
+ onClick: () => {
+ handleSave(fieldKey, {
+ type,
+ name: columnLabel,
+ fieldName: fieldKey,
+ key: fieldKey,
+ config: {},
+ ...data.initializeColumn,
+ });
+ if (requireConfiguration) {
+ openSettings({
+ type,
+ name: columnLabel,
+ fieldName: fieldKey,
+ key: fieldKey,
+ config: {},
+ ...data.initializeColumn,
+ });
+ } else handleClose();
+ analytics.logEvent("create_column", {
+ type,
+ });
+ },
+ disabled: !columnLabel || !fieldKey || !type,
+ children: requireConfiguration ? "Next" : "Add",
+ },
+ secondary: {
+ onClick: handleClose,
+ children: "Cancel",
+ },
+ }}
+ />
+ );
+}
diff --git a/src/components/Table/ColumnMenu/Subheading.tsx b/src/components/Table/ColumnMenu/Subheading.tsx
new file mode 100644
index 000000000..49e413905
--- /dev/null
+++ b/src/components/Table/ColumnMenu/Subheading.tsx
@@ -0,0 +1,19 @@
+import { useTheme, Typography, TypographyProps } from "@material-ui/core";
+
+export default function Subheading(props: TypographyProps<"h2">) {
+ const theme = useTheme();
+
+ return (
+
+ );
+}
diff --git a/src/components/Table/ColumnMenu/TypeChange.tsx b/src/components/Table/ColumnMenu/TypeChange.tsx
new file mode 100644
index 000000000..93688abf6
--- /dev/null
+++ b/src/components/Table/ColumnMenu/TypeChange.tsx
@@ -0,0 +1,50 @@
+import { useState } from "react";
+
+import { IMenuModalProps } from ".";
+import Modal from "components/Modal";
+import FieldsDropdown from "./FieldsDropdown";
+import { analytics } from "analytics";
+export default function FormDialog({
+ fieldName,
+ type,
+ open,
+ handleClose,
+ handleSave,
+}: IMenuModalProps) {
+ const [newType, setType] = useState(type);
+
+ if (!open) return null;
+
+ return (
+ {
+ setType(newType.target.value);
+ }}
+ />
+ }
+ actions={{
+ primary: {
+ onClick: () => {
+ handleSave(fieldName, { type: newType });
+ handleClose();
+ analytics.logEvent("change_column_type", {
+ newType,
+ prevType: type,
+ });
+ },
+ children: "Update",
+ },
+ secondary: {
+ onClick: handleClose,
+ children: "Cancel",
+ },
+ }}
+ maxWidth="xs"
+ />
+ );
+}
diff --git a/src/components/Table/ColumnMenu/index.tsx b/src/components/Table/ColumnMenu/index.tsx
new file mode 100644
index 000000000..de77ca4a7
--- /dev/null
+++ b/src/components/Table/ColumnMenu/index.tsx
@@ -0,0 +1,317 @@
+import React, { useState, useEffect } from "react";
+
+import { Menu } from "@material-ui/core";
+import LockOpenIcon from "@material-ui/icons/LockOpen";
+import LockIcon from "@material-ui/icons/Lock";
+import VisibilityOffIcon from "@material-ui/icons/VisibilityOffOutlined";
+import VisibilityIcon from "@material-ui/icons/VisibilityOutlined";
+import FreezeIcon from "assets/icons/Freeze";
+import UnfreezeIcon from "assets/icons/Unfreeze";
+import CellResizeIcon from "assets/icons/CellResize";
+import ArrowDownwardIcon from "@material-ui/icons/ArrowDownward";
+import ArrowUpwardIcon from "@material-ui/icons/ArrowUpward";
+import EditIcon from "@material-ui/icons/EditOutlined";
+// import ReorderIcon from "@material-ui/icons/Reorder";
+import SettingsIcon from "@material-ui/icons/SettingsOutlined";
+import ColumnPlusBeforeIcon from "assets/icons/ColumnPlusBefore";
+import ColumnPlusAfterIcon from "assets/icons/ColumnPlusAfter";
+import ColumnRemoveIcon from "assets/icons/ColumnRemove";
+
+import MenuContents from "./MenuContents";
+import NameChange from "./NameChange";
+import NewColumn from "./NewColumn";
+import TypeChange from "./TypeChange";
+import FieldSettings from "./FieldSettings";
+
+import { useRowyContext } from "contexts/RowyContext";
+import { FieldType } from "constants/fields";
+import { getFieldProp } from "components/fields";
+
+import { Column } from "react-data-grid";
+import { PopoverProps } from "@material-ui/core";
+
+const INITIAL_MODAL = { type: "", data: {} };
+
+enum ModalStates {
+ nameChange = "NAME_CHANGE",
+ typeChange = "TYPE_CHANGE",
+ new = "NEW_COLUMN",
+ settings = "COLUMN_SETTINGS",
+}
+
+type SelectedColumnHeader = {
+ column: Column & { [key: string]: any };
+ anchorEl: PopoverProps["anchorEl"];
+};
+export type ColumnMenuRef = {
+ selectedColumnHeader: SelectedColumnHeader | null;
+ setSelectedColumnHeader: React.Dispatch<
+ React.SetStateAction
+ >;
+};
+
+export interface IMenuModalProps {
+ name: string;
+ fieldName: string;
+ type: FieldType;
+
+ open: boolean;
+ config: Record;
+
+ handleClose: () => void;
+ handleSave: (fieldName: string, config: Record) => void;
+}
+
+export default function ColumnMenu() {
+ const [modal, setModal] = useState(INITIAL_MODAL);
+ const { tableState, tableActions, columnMenuRef } = useRowyContext();
+
+ const [selectedColumnHeader, setSelectedColumnHeader] = useState(null);
+ if (columnMenuRef)
+ columnMenuRef.current = {
+ selectedColumnHeader,
+ setSelectedColumnHeader,
+ } as any;
+
+ const { column, anchorEl } = (selectedColumnHeader ?? {}) as any;
+
+ useEffect(() => {
+ if (column && column.type === FieldType.last) {
+ setModal({
+ type: ModalStates.new,
+ data: {
+ initializeColumn: { index: column.index ? column.index + 1 : 0 },
+ },
+ });
+ }
+ }, [column]);
+ if (!tableState || !tableActions) return null;
+ const { orderBy } = tableState;
+
+ const actions = tableActions!.column;
+
+ const handleClose = () => {
+ if (!setSelectedColumnHeader) return;
+ setSelectedColumnHeader({
+ column: column!,
+ anchorEl: null,
+ });
+ setTimeout(() => setSelectedColumnHeader(null), 300);
+ };
+
+ const isConfigurable = Boolean(
+ getFieldProp("settings", column?.type) ||
+ getFieldProp("initializable", column?.type)
+ );
+
+ if (!column) return null;
+
+ const isSorted = orderBy?.[0]?.key === column.key;
+ const isAsc = isSorted && orderBy?.[0]?.direction === "asc";
+
+ const clearModal = () => {
+ setModal(INITIAL_MODAL);
+ setTimeout(() => handleClose(), 300);
+ };
+
+ const handleModalSave = (key: string, update: Record) => {
+ actions.update(key, update);
+ };
+ const openSettings = (column) => {
+ setSelectedColumnHeader({
+ column,
+ });
+ setModal({ type: ModalStates.settings, data: { column } });
+ };
+ const menuItems = [
+ {
+ type: "subheader",
+ label: column.name,
+ },
+ {
+ label: "Lock",
+ activeLabel: "Unlock",
+ icon: ,
+ activeIcon: ,
+ onClick: () => {
+ actions.update(column.key, { editable: !column.editable });
+ handleClose();
+ },
+ active: !column.editable,
+ },
+ {
+ label: "Freeze",
+ activeLabel: "Unfreeze",
+ icon: ,
+ activeIcon: ,
+ onClick: () => {
+ actions.update(column.key, { fixed: !column.fixed });
+ handleClose();
+ },
+ active: column.fixed,
+ },
+ {
+ label: "Enable resize",
+ activeLabel: "Disable resize",
+ icon: ,
+ onClick: () => {
+ actions.update(column.key, { resizable: !column.resizable });
+ handleClose();
+ },
+ active: column.resizable,
+ },
+ {
+ label: "Sort: descending",
+ activeLabel: "Sorted: descending",
+ icon: ,
+ onClick: () => {
+ tableActions.table.orderBy(
+ isSorted && !isAsc ? [] : [{ key: column.key, direction: "desc" }]
+ );
+ handleClose();
+ },
+ active: isSorted && !isAsc,
+ disabled: column.type === FieldType.id,
+ },
+ {
+ label: "Sort: ascending",
+ activeLabel: "Sorted: ascending",
+ icon: ,
+ onClick: () => {
+ tableActions.table.orderBy(
+ isSorted && isAsc ? [] : [{ key: column.key, direction: "asc" }]
+ );
+ handleClose();
+ },
+ active: isSorted && isAsc,
+ disabled: column.type === FieldType.id,
+ },
+ { type: "subheader", label: "Edit" },
+ {
+ label: "Rename…",
+ icon: ,
+ onClick: () => {
+ setModal({ type: ModalStates.nameChange, data: {} });
+ },
+ },
+ {
+ label: `Edit type: ${getFieldProp("name", column.type)}…`,
+ // This is based off the cell type
+ icon: getFieldProp("icon", column.type),
+ onClick: () => {
+ setModal({ type: ModalStates.typeChange, data: { column } });
+ },
+ },
+ {
+ label: `Column settings…`,
+ // This is based off the cell type
+ icon: ,
+ onClick: () => {
+ openSettings(column);
+ },
+ disabled: !isConfigurable,
+ },
+ // {
+ // label: "Re-order",
+ // icon: ,
+ // onClick: () => alert("REORDER"),
+ // },
+ {
+ label: "Add new to left…",
+ icon: ,
+ onClick: () =>
+ setModal({
+ type: ModalStates.new,
+ data: {
+ initializeColumn: { index: column.index ? column.index - 1 : 0 },
+ },
+ }),
+ },
+ {
+ label: "Add new to right…",
+ icon: ,
+ onClick: () =>
+ setModal({
+ type: ModalStates.new,
+ data: {
+ initializeColumn: { index: column.index ? column.index + 1 : 0 },
+ },
+ }),
+ },
+ {
+ label: "Hide for everyone",
+ activeLabel: "Show",
+ icon: ,
+ activeIcon: ,
+ onClick: () => {
+ actions.update(column.key, { hidden: !column.hidden });
+ handleClose();
+ },
+ active: column.hidden,
+ color: "error" as "error",
+ },
+ {
+ label: "Delete column",
+ icon: ,
+ onClick: () => {
+ actions.remove(column.key);
+ handleClose();
+ },
+ color: "error" as "error",
+ },
+ ];
+
+ const menuModalProps = {
+ name: column.name,
+ fieldName: column.key,
+ type: column.type,
+
+ open: modal.type === ModalStates.typeChange,
+ config: column.config,
+
+ handleClose: clearModal,
+ handleSave: handleModalSave,
+ };
+
+ return (
+ <>
+ {column.type !== FieldType.last && (
+
+ )}
+ {column && (
+ <>
+
+
+
+
+ >
+ )}
+ >
+ );
+}
diff --git a/src/components/Table/EmptyTable.tsx b/src/components/Table/EmptyTable.tsx
new file mode 100644
index 000000000..2078e1370
--- /dev/null
+++ b/src/components/Table/EmptyTable.tsx
@@ -0,0 +1,155 @@
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { Grid, Typography, Button } from "@material-ui/core";
+import ImportIcon from "assets/icons/Import";
+import AddColumnIcon from "assets/icons/AddColumn";
+
+import { APP_BAR_HEIGHT } from "components/Navigation";
+
+import { useRowyContext } from "contexts/RowyContext";
+import ColumnMenu from "./ColumnMenu";
+import ImportWizard from "components/Wizards/ImportWizard";
+import ImportCSV from "./TableHeader/ImportCsv";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: {
+ height: `calc(100vh - ${APP_BAR_HEIGHT}px)`,
+ width: 300,
+ margin: "0 auto",
+ textAlign: "center",
+ userSelect: "none",
+ },
+
+ tablePath: {
+ fontFamily: theme.typography.fontFamilyMono,
+ textTransform: "none",
+ },
+ })
+);
+
+export default function EmptyTable() {
+ const classes = useStyles();
+ const { tableState, importWizardRef, columnMenuRef } = useRowyContext();
+
+ if (tableState?.rows && tableState?.rows.length > 0)
+ return (
+
+
+
+ You have existing data in your Firestore collection
+
+
+ “{tableState?.tablePath}”
+
+
+
+
+
+
+ You can start by importing this existing data to this table
+
+
+
+
+ }
+ onClick={() => importWizardRef?.current?.setOpen(true)}
+ >
+ Import
+
+
+
+
+
+ );
+
+ return (
+
+
+
+ You have no data in this table
+
+
+
+
+
+ You can start by importing data from an external CSV file
+
+
+
+
+ (
+ }
+ onClick={onClick}
+ >
+ Import CSV
+
+ )}
+ PopoverProps={{
+ anchorOrigin: {
+ vertical: "bottom",
+ horizontal: "center",
+ },
+ transformOrigin: {
+ vertical: "top",
+ horizontal: "center",
+ },
+ }}
+ />
+
+
+
+
+
+
+ Or you can manually add new columns and rows
+
+
+
+
+ }
+ onClick={(event) =>
+ columnMenuRef?.current?.setSelectedColumnHeader({
+ column: { isNew: true, key: "new", type: "LAST" } as any,
+ anchorEl: event.currentTarget,
+ })
+ }
+ disabled={!columnMenuRef?.current}
+ >
+ Add Column
+
+
+
+
+
+ );
+}
diff --git a/www/src/components/Table/Filters/Row.tsx b/src/components/Table/Filters/Row.tsx
similarity index 78%
rename from www/src/components/Table/Filters/Row.tsx
rename to src/components/Table/Filters/Row.tsx
index d87212b2b..321f58177 100644
--- a/www/src/components/Table/Filters/Row.tsx
+++ b/src/components/Table/Filters/Row.tsx
@@ -1,5 +1,5 @@
const FiltersRow = () => {
- return <>>;
+ return <>>;
};
export default FiltersRow;
diff --git a/src/components/Table/Filters/index.tsx b/src/components/Table/Filters/index.tsx
new file mode 100644
index 000000000..7a6b180a9
--- /dev/null
+++ b/src/components/Table/Filters/index.tsx
@@ -0,0 +1,537 @@
+import React, { useState, useEffect } from "react";
+import _find from "lodash/find";
+import _sortBy from "lodash/sortBy";
+import _isEmpty from "lodash/isEmpty";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import {
+ Popover,
+ Button,
+ Typography,
+ IconButton,
+ Grid,
+ MenuItem,
+ TextField,
+ Switch,
+ Chip,
+} from "@material-ui/core";
+import FilterIcon from "@material-ui/icons/FilterList";
+import CloseIcon from "@material-ui/icons/Close";
+
+import MultiSelect from "@antlerengineering/multiselect";
+import ButtonWithStatus from "components/ButtonWithStatus";
+
+import { FieldType } from "constants/fields";
+import { RowyFilter } from "hooks/useRowy";
+import { useRowyContext } from "contexts/RowyContext";
+
+import { useAppContext } from "contexts/AppContext";
+import { DocActions } from "hooks/useDoc";
+const getType = (column) =>
+ column.type === FieldType.derivative
+ ? column.config.renderFieldType
+ : column.type;
+const OPERATORS = [
+ {
+ value: "==",
+ label: "Equals",
+ compatibleTypes: [
+ FieldType.phone,
+ FieldType.color,
+ FieldType.date,
+ FieldType.dateTime,
+ FieldType.shortText,
+ FieldType.singleSelect,
+ FieldType.url,
+ FieldType.email,
+ FieldType.checkbox,
+ ],
+ },
+ {
+ value: "in",
+ label: "matches any of",
+ compatibleTypes: [FieldType.singleSelect],
+ },
+ // {
+ // value: "array-contains",
+ // label: "includes",
+ // compatibleTypes: [FieldType.connectTable],
+ // },
+ // {
+ // value: "array-contains",
+ // label: "Has",
+ // compatibleTypes: [FieldType.multiSelect],
+ // },
+ {
+ value: "array-contains-any",
+ label: "Has any",
+ compatibleTypes: [FieldType.multiSelect, FieldType.connectTable],
+ },
+ { value: "<", label: "<", compatibleTypes: [FieldType.number] },
+ { value: "<=", label: "<=", compatibleTypes: [FieldType.number] },
+ { value: "==", label: "==", compatibleTypes: [FieldType.number] },
+ { value: ">=", label: ">=", compatibleTypes: [FieldType.number] },
+ { value: ">", label: ">", compatibleTypes: [FieldType.number] },
+ {
+ value: "<",
+ label: "before",
+ compatibleTypes: [FieldType.date, FieldType.dateTime],
+ },
+ {
+ value: ">=",
+ label: "after",
+ compatibleTypes: [FieldType.date, FieldType.dateTime],
+ },
+];
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ paper: { width: 640 },
+
+ closeButton: {
+ position: "absolute",
+ top: theme.spacing(0.5),
+ right: theme.spacing(0.5),
+ },
+
+ content: { padding: theme.spacing(4) },
+
+ topRow: { marginBottom: theme.spacing(3.5) },
+ bottomButtons: { marginTop: theme.spacing(4.5) },
+
+ activeButton: {
+ borderTopRightRadius: 0,
+ borderBottomRightRadius: 0,
+ position: "relative",
+ zIndex: 1,
+ },
+
+ filterChip: {
+ borderTopLeftRadius: 0,
+ borderBottomLeftRadius: 0,
+ borderTopRightRadius: theme.shape.borderRadius,
+ borderBottomRightRadius: theme.shape.borderRadius,
+ borderLeft: "none",
+ backgroundColor: theme.palette.background.paper,
+ height: 32,
+ // paddingLeft: theme.shape.borderRadius,
+ // marginLeft: -theme.shape.borderRadius,
+ paddingRight: theme.spacing(0.5) + " !important",
+ },
+ filterChipLabel: {
+ padding: theme.spacing(0, 1.5),
+ },
+ })
+);
+
+const UNFILTERABLES = [
+ FieldType.image,
+ FieldType.file,
+ FieldType.action,
+ FieldType.subTable,
+ FieldType.last,
+ FieldType.longText,
+];
+const Filters = () => {
+ const { tableState, tableActions } = useRowyContext();
+ const { userDoc } = useAppContext();
+
+ useEffect(() => {
+ if (userDoc.state.doc && tableState?.tablePath) {
+ if (userDoc.state.doc.tables?.[tableState?.tablePath]?.filters) {
+ tableActions?.table.filter(
+ userDoc.state.doc.tables[tableState?.tablePath].filters
+ );
+ tableActions?.table.orderBy();
+ }
+ }
+ }, [userDoc.state, tableState?.tablePath]);
+ const filterColumns = _sortBy(Object.values(tableState!.columns), "index")
+ .filter((c) => !UNFILTERABLES.includes(c.type))
+ .map((c) => ({
+ key: c.key,
+ label: c.name,
+ type: c.type,
+ options: c.options,
+ ...c,
+ }));
+ const classes = useStyles();
+ const filters = [];
+
+ const [selectedColumn, setSelectedColumn] = useState();
+
+ const [query, setQuery] = useState({
+ key: "",
+ operator: "",
+ value: "",
+ });
+
+ useEffect(() => {
+ if (selectedColumn) {
+ let updatedQuery: RowyFilter = {
+ key: selectedColumn.key,
+ operator: "",
+ value: "",
+ };
+ const type = getType(selectedColumn);
+ if (
+ [
+ FieldType.phone,
+ FieldType.shortText,
+ FieldType.url,
+ FieldType.email,
+ FieldType.checkbox,
+ ].includes(type)
+ ) {
+ updatedQuery = { ...updatedQuery, operator: "==" };
+ }
+ if (type === FieldType.checkbox) {
+ updatedQuery = { ...updatedQuery, value: false };
+ }
+ if (type === FieldType.connectTable) {
+ updatedQuery = {
+ key: `${selectedColumn.key}ID`,
+ operator: "array-contains-any",
+ value: [],
+ };
+ }
+ if (type === FieldType.multiSelect) {
+ updatedQuery = {
+ ...updatedQuery,
+ operator: "array-contains-any",
+ value: [],
+ };
+ }
+ setQuery(updatedQuery);
+ }
+ }, [selectedColumn]);
+
+ const operators = selectedColumn
+ ? OPERATORS.filter((operator) =>
+ operator.compatibleTypes.includes(getType(selectedColumn))
+ )
+ : [];
+
+ const [anchorEl, setAnchorEl] = useState(null);
+ const handleClose = () => setAnchorEl(null);
+
+ const handleClick = (event: React.MouseEvent) => {
+ setAnchorEl(anchorEl ? null : event.currentTarget);
+ };
+
+ const handleChangeColumn = (e) => {
+ const column = _find(filterColumns, (c) => c.key === e.target.value);
+ setSelectedColumn(column);
+ };
+ const open = Boolean(anchorEl);
+
+ const id = open ? "simple-popper" : undefined;
+
+ const renderInputField = (selectedColumn, operator) => {
+ const type = getType(selectedColumn);
+ switch (type) {
+ case FieldType.checkbox:
+ return (
+ {
+ setQuery((query) => ({ ...query, value: e.target.checked }));
+ }}
+ />
+ );
+ case FieldType.email:
+ case FieldType.phone:
+ case FieldType.shortText:
+ case FieldType.longText:
+ case FieldType.url:
+ return (
+ {
+ const value = e.target.value;
+ if (value) setQuery((query) => ({ ...query, value: value }));
+ }}
+ variant="filled"
+ hiddenLabel
+ placeholder="Text value"
+ />
+ );
+ case FieldType.number:
+ return (
+ {
+ const value = e.target.value;
+ if (query.value || value)
+ setQuery((query) => ({
+ ...query,
+ value: value !== "" ? parseFloat(value) : "",
+ }));
+ }}
+ value={typeof query.value === "number" ? query.value : ""}
+ variant="filled"
+ hiddenLabel
+ type="number"
+ placeholder="number value"
+ />
+ );
+
+ case FieldType.singleSelect:
+ if (operator === "in")
+ return (
+ setQuery((query) => ({ ...query, value }))}
+ options={
+ selectedColumn.config.options
+ ? selectedColumn.config.options.sort()
+ : []
+ }
+ label=""
+ value={Array.isArray(query?.value) ? query.value : []}
+ TextFieldProps={{ hiddenLabel: true }}
+ />
+ );
+
+ return (
+ {
+ if (value !== null) setQuery((query) => ({ ...query, value }));
+ }}
+ options={
+ selectedColumn.config.options
+ ? selectedColumn.config.options.sort()
+ : []
+ }
+ label=""
+ value={typeof query?.value === "string" ? query.value : null}
+ TextFieldProps={{ hiddenLabel: true }}
+ />
+ );
+
+ case FieldType.multiSelect:
+ return (
+ setQuery((query) => ({ ...query, value }))}
+ value={query.value as string[]}
+ max={10}
+ options={
+ selectedColumn.config.options
+ ? selectedColumn.config.options.sort()
+ : []
+ }
+ label={""}
+ searchable={false}
+ freeText={true}
+ />
+ );
+
+ case FieldType.date:
+ case FieldType.dateTime:
+ return <>//TODO:Date/Time picker>;
+ default:
+ return <>Not available>;
+ // return ;
+ break;
+ }
+ };
+
+ const handleUpdateFilters = (filters: RowyFilter[]) => {
+ userDoc.dispatch({
+ action: DocActions.update,
+ data: {
+ tables: { [`${tableState?.tablePath}`]: { filters } },
+ },
+ });
+ };
+ return (
+ <>
+
+ }
+ active={tableState?.filters && tableState?.filters.length > 0}
+ className={
+ tableState?.filters && tableState?.filters.length > 0
+ ? classes.activeButton
+ : ""
+ }
+ >
+ {tableState?.filters && tableState?.filters.length > 0
+ ? "Filtered"
+ : "Filter"}
+
+
+ {(tableState?.filters ?? []).map((filter) => (
+ handleUpdateFilters([])}
+ classes={{
+ root: classes.filterChip,
+ label: classes.filterChipLabel,
+ }}
+ variant="outlined"
+ />
+ ))}
+
+
+
+
+
+
+
+ {/*
+
+ Results match
+
+
+
+
+ all
+ any
+
+
+
+
+ of the filter criteria.
+
+ */}
+
+
+
+ Column
+
+
+ Condition
+
+
+ Value
+
+
+
+
+
+
+
+ Select Column
+
+ {filterColumns.map((c) => (
+
+ {c.label}
+
+ ))}
+
+
+
+
+ {
+ setQuery((query) => ({
+ ...query,
+ operator: e.target.value as string,
+ }));
+ }}
+ SelectProps={{ displayEmpty: true }}
+ >
+
+ Select Condition
+
+ {operators.map((operator) => (
+
+ {operator.label}
+
+ ))}
+
+
+
+
+ {query.operator &&
+ renderInputField(selectedColumn, query.operator)}
+
+
+
+
+ {/* + ADD FILTER */}
+ {
+ handleUpdateFilters([]);
+ setQuery({
+ key: "",
+ operator: "",
+ value: "",
+ });
+ setSelectedColumn(null);
+ //handleClose();
+ }}
+ >
+ Clear
+
+ {
+ handleUpdateFilters([query]);
+ handleClose();
+ }}
+ >
+ Apply
+
+
+
+
+ >
+ );
+};
+
+export default Filters;
diff --git a/src/components/Table/FinalColumnHeader.tsx b/src/components/Table/FinalColumnHeader.tsx
new file mode 100644
index 000000000..baf29af8b
--- /dev/null
+++ b/src/components/Table/FinalColumnHeader.tsx
@@ -0,0 +1,77 @@
+import { Column } from "react-data-grid";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { Grid, Button } from "@material-ui/core";
+import AddColumnIcon from "assets/icons/AddColumn";
+
+import { useRowyContext } from "contexts/RowyContext";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ "@global": {
+ ".rdg-header-row .rdg-cell.final-column-header": {
+ border: "none",
+ ".rdg.rdg &": { padding: theme.spacing(0, 0.75) },
+
+ "&::before": {
+ content: "''",
+ display: "block",
+ width: 46,
+ height: "100%",
+
+ position: "absolute",
+ top: 0,
+ left: 0,
+
+ border: "1px solid var(--border-color)",
+ borderLeftWidth: 0,
+ borderTopRightRadius: theme.shape.borderRadius,
+ borderBottomRightRadius: theme.shape.borderRadius,
+ },
+ },
+ },
+
+ root: {
+ height: "100%",
+ width: "auto",
+ },
+
+ button: { zIndex: 1 },
+ })
+);
+
+const FinalColumnHeader: Column["headerRenderer"] = ({ column }) => {
+ const classes = useStyles();
+
+ const { columnMenuRef } = useRowyContext();
+ if (!columnMenuRef) return null;
+
+ const handleClick = (
+ event: React.MouseEvent
+ ) =>
+ columnMenuRef?.current?.setSelectedColumnHeader({
+ column,
+ anchorEl: event.currentTarget,
+ });
+
+ return (
+
+ }
+ >
+ Add Column
+
+
+ );
+};
+
+export default FinalColumnHeader;
diff --git a/src/components/Table/HiddenFields.tsx b/src/components/Table/HiddenFields.tsx
new file mode 100644
index 000000000..742d68e5a
--- /dev/null
+++ b/src/components/Table/HiddenFields.tsx
@@ -0,0 +1,148 @@
+import { useRef, useState, useEffect } from "react";
+import _isEqual from "lodash/isEqual";
+import _sortBy from "lodash/sortBy";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import VisibilityOffIcon from "@material-ui/icons/VisibilityOffOutlined";
+
+import MultiSelect from "@antlerengineering/multiselect";
+import ButtonWithStatus from "components/ButtonWithStatus";
+import Column from "components/Wizards/Column";
+
+import { useRowyContext } from "contexts/RowyContext";
+import { useAppContext } from "contexts/AppContext";
+import { DocActions } from "hooks/useDoc";
+import { formatSubTableName } from "../../utils/fns";
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ listbox: {},
+ option: {
+ "$listbox &": {
+ padding: theme.spacing(0, 2),
+ marginBottom: -1,
+
+ "&::after": { content: "none" },
+
+ "&:hover, &.Mui-focused, &.Mui-focusVisible": {
+ backgroundColor: "transparent",
+
+ position: "relative",
+ zIndex: 2,
+
+ "& > div": {
+ color: theme.palette.text.primary,
+ borderColor: "currentColor",
+ boxShadow: `0 0 0 1px ${theme.palette.text.primary} inset`,
+ },
+ "& $hiddenIcon": { opacity: 0.5 },
+ },
+
+ '&[aria-selected="true"], &[aria-selected="true"].Mui-focused, &[aria-selected="true"].Mui-focusVisible': {
+ backgroundColor: "transparent",
+
+ position: "relative",
+ zIndex: 1,
+
+ "& $hiddenIcon": { opacity: 1 },
+ },
+ },
+ },
+
+ hiddenIcon: { opacity: 0 },
+ })
+);
+
+export default function HiddenFields() {
+ const classes = useStyles();
+ const buttonRef = useRef(null);
+
+ const { tableState } = useRowyContext();
+ const { userDoc } = useAppContext();
+
+ const [open, setOpen] = useState(false);
+
+ // Store local selection here
+ const [hiddenFields, setHiddenFields] = useState([]);
+
+ // Initialise hiddenFields from user doc
+ const userDocHiddenFields =
+ userDoc.state.doc?.tables?.[formatSubTableName(tableState?.tablePath!)]
+ ?.hiddenFields;
+ useEffect(() => {
+ if (userDocHiddenFields) setHiddenFields(userDocHiddenFields);
+ else setHiddenFields([]);
+ }, [userDocHiddenFields]);
+
+ if (!tableState || !userDoc) return null;
+
+ const tableColumns = _sortBy(
+ Object.entries(tableState.columns).filter(([key]) => key !== "undefined"),
+ (column) => column[1].index
+ ).map(([key]) => ({
+ value: key,
+ label: tableState.columns[key].name,
+ }));
+
+ // Save when MultiSelect closes
+ const handleSave = () => {
+ // Only update if there were any changes because it’s slow to update
+ if (!_isEqual(hiddenFields, userDocHiddenFields))
+ userDoc.dispatch({
+ action: DocActions.update,
+ data: {
+ tables: {
+ [formatSubTableName(tableState?.tablePath)]: { hiddenFields },
+ },
+ },
+ });
+
+ setOpen(false);
+ };
+ const renderOption = (props, option, { selected }) => (
+
+ }
+ active={selected}
+ />
+
+ );
+ return (
+ <>
+ }
+ onClick={() => setOpen((o) => !o)}
+ active={hiddenFields.length > 0}
+ ref={buttonRef}
+ >
+ {hiddenFields.length > 0 ? `${hiddenFields.length} Hidden` : "Hide"}
+
+
+ >
+ );
+}
diff --git a/src/components/Table/HotKeys.tsx b/src/components/Table/HotKeys.tsx
new file mode 100644
index 000000000..fa984711f
--- /dev/null
+++ b/src/components/Table/HotKeys.tsx
@@ -0,0 +1,103 @@
+import useHotkeys from "../../hooks/useHotkeys";
+import { FieldType } from "constants/fields";
+import { useAppContext } from "contexts/AppContext";
+
+// TODO: Hook up to RowyContext
+const onSubmit: any = () => () => {};
+
+/**
+ * Listens Hot Keys combination keys to trigger keyboard shortcuts
+ */
+const Hotkeys = (props: any) => {
+ const { selectedCell } = props;
+ const { currentUser } = useAppContext();
+
+ useHotkeys(
+ "cmd+c",
+ () => {
+ handleCopy();
+ },
+ [selectedCell]
+ );
+ useHotkeys(
+ "ctrl+c",
+ () => {
+ handleCopy();
+ },
+ [selectedCell]
+ );
+ useHotkeys(
+ "cmd+v",
+ () => {
+ handlePaste();
+ },
+ [selectedCell]
+ );
+ useHotkeys(
+ "ctrl+v",
+ () => {
+ handlePaste();
+ },
+ [selectedCell]
+ );
+ useHotkeys(
+ "ctrl+x",
+ () => {
+ handleCut();
+ },
+ [selectedCell]
+ );
+ useHotkeys(
+ "cmd+x",
+ () => {
+ handleCut();
+ },
+ [selectedCell]
+ );
+ const stringFields = [
+ FieldType.email,
+ FieldType.shortText,
+ FieldType.phone,
+ FieldType.singleSelect,
+ FieldType.longText,
+ FieldType.url,
+ ];
+ const numberFields = [FieldType.number, FieldType.rating];
+ /**
+ * populate cell from clipboard
+ */
+ const handlePaste = async () => {
+ const { row, column } = selectedCell;
+ const newValue = await navigator.clipboard.readText();
+ if (stringFields.includes(column.type))
+ onSubmit(column.key, row, currentUser?.uid)(newValue);
+ else if (numberFields.includes(column.type)) {
+ const numberValue = parseInt(newValue, 10);
+ if (`${numberValue}` !== "NaN") {
+ onSubmit(column.key, row, currentUser?.uid)(numberValue);
+ }
+ }
+ };
+ const supportedFields = [...stringFields, ...numberFields];
+ /**
+ * copy cell content to clipboard works only on supported fields
+ */
+ const handleCopy = () => {
+ const { row, column } = selectedCell;
+ if (supportedFields.includes(column.type)) {
+ navigator.clipboard.writeText(row[column.key]);
+ }
+ };
+ /**
+ * copy cell content to clipboard and clears cell(only on supported fields)
+ */
+ const handleCut = () => {
+ const { row, column } = selectedCell;
+ if (supportedFields.includes(column.type)) {
+ navigator.clipboard.writeText(row[column.key]);
+ onSubmit(column.key, row)(null);
+ }
+ };
+ return <>>;
+};
+export default Hotkeys;
diff --git a/src/components/Table/Settings/Menu.tsx b/src/components/Table/Settings/Menu.tsx
new file mode 100644
index 000000000..02c6f456e
--- /dev/null
+++ b/src/components/Table/Settings/Menu.tsx
@@ -0,0 +1,61 @@
+import React from "react";
+import IconButton from "@material-ui/core/IconButton";
+import Menu from "@material-ui/core/Menu";
+import MenuItem from "@material-ui/core/MenuItem";
+import MoreVertIcon from "@material-ui/icons/MoreVert";
+
+const options = ["Webhooks", "Rules", "Algolia", "CollectionSync"];
+
+const ITEM_HEIGHT = 48;
+
+export default function SettingsMenu({ modal, setModal }) {
+ const [anchorEl, setAnchorEl] = React.useState(null);
+ const open = Boolean(anchorEl);
+
+ const handleClick = (event: React.MouseEvent) => {
+ setAnchorEl(event.currentTarget);
+ };
+
+ const handleClose = (option: string) => () => {
+ setModal(option);
+ setAnchorEl(null);
+ };
+
+ return (
+
+
+
+
+
+
+ );
+}
diff --git a/src/components/Table/Settings/Webhooks.tsx b/src/components/Table/Settings/Webhooks.tsx
new file mode 100644
index 000000000..71abb23f4
--- /dev/null
+++ b/src/components/Table/Settings/Webhooks.tsx
@@ -0,0 +1,186 @@
+import React, { useState, useEffect } from "react";
+import { makeStyles, createStyles } from "@material-ui/styles";
+
+import Button from "@material-ui/core/Button";
+import Dialog, { DialogProps } from "@material-ui/core/Dialog";
+import DialogActions from "@material-ui/core/DialogActions";
+import DialogContent from "@material-ui/core/DialogContent";
+
+import DialogTitle from "@material-ui/core/DialogTitle";
+import FormControl from "@material-ui/core/FormControl";
+import Typography from "@material-ui/core/Typography";
+
+import FormControlLabel from "@material-ui/core/FormControlLabel";
+import InputLabel from "@material-ui/core/InputLabel";
+import MenuItem from "@material-ui/core/MenuItem";
+import Select from "@material-ui/core/Select";
+import Switch from "@material-ui/core/Switch";
+import CodeEditor from "../editors/CodeEditor";
+import { useRowyContext } from "contexts/RowyContext";
+import { WEBHOOK_URL } from "../../../firebase";
+import { makeId } from "../../../utils/fns";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ form: {
+ display: "flex",
+ flexDirection: "column",
+ margin: "auto",
+ width: "fit-content",
+ },
+ formControl: {
+ marginTop: theme.spacing(2),
+ minWidth: 120,
+ },
+ formControlLabel: {
+ marginTop: theme.spacing(1),
+ },
+ })
+);
+
+enum WebhookTypes {
+ custom = "CUSTOM",
+ typeForm = "TYPE_FORM",
+}
+const EmptyState = {
+ enabled: false,
+ type: WebhookTypes.custom,
+ secret: "",
+ customParser: "",
+};
+export default function WebhooksDialog({ open, handleClose }) {
+ const classes = useStyles();
+
+ const { tableState, tableActions } = useRowyContext();
+
+ const [state, setState] = useState<{
+ enabled: boolean;
+ type: WebhookTypes;
+ secret: string;
+ customParser: string;
+ }>(EmptyState);
+ const tableFields = Object.keys(tableState?.columns as any);
+ const fullWidth = true;
+ const maxWidth: DialogProps["maxWidth"] = "xl";
+ const handleChange = (key: string) => (value: any) => {
+ setState((s) => ({ ...s, [key]: value }));
+ };
+ const initializeWebhooksConfig = () => {
+ const secret = makeId(32);
+ handleChange("secret")(secret);
+ setState({ ...EmptyState, secret });
+ tableActions?.table.updateConfig("webhooks", {
+ enabled: false,
+ type: WebhookTypes.custom,
+ secret,
+ customParser: "", // TODO: add a boilerplate/example
+ });
+ };
+ useEffect(() => {
+ if (
+ tableState &&
+ !tableState.config.tableConfig.loading &&
+ !tableState?.config.webhooks &&
+ !state.secret
+ ) {
+ initializeWebhooksConfig();
+ } else if (tableState?.config.webhooks) {
+ setState({ ...tableState?.config.webhooks });
+ }
+ }, [tableState?.config]);
+
+ const handleWebhookTypeChange = (
+ event: React.ChangeEvent<{ value: unknown }>
+ ) => {
+ handleChange("type")(event.target.value as WebhookTypes);
+ };
+
+ const handleSave = async () => {
+ handleClose();
+ await tableActions?.table.updateConfig("webhooks", {
+ ...state,
+ });
+ };
+ const handleCancel = () => {
+ handleClose();
+ setState({ ...tableState?.config.webhooks });
+ };
+ return (
+
+
+ Webhooks
+
+
+ }
+ label={"Enable webhooks for this table"}
+ labelPlacement="end"
+ checked={state.enabled}
+ onChange={
+ () => {
+ handleChange("enabled")(!state.enabled);
+ }
+ // handleChange("isCollectionGroup", !formState.isCollectionGroup)
+ }
+ // classes={{ root: classes.formControlLabel, label: classes.label }}
+ />
+ Webhook Type
+
+ Typeform
+ Custom
+
+
+ {state.type === WebhookTypes.custom && (
+
+ )}
+
+ {state.type === WebhookTypes.typeForm && (
+ <>
+ Web hook url:
+
+ {WEBHOOK_URL}?tablePath={tableState?.tablePath}
+ &type=TYPE_FORM&secret={state.secret}
+
+ instructions:
+
+ please set the question reference in typeform to the following
+ field keys :{" "}
+ {tableFields.map((key) => (
+ <>
+ {" "}
+ {key} ,
+ >
+ ))}
+
+ >
+ )}
+
+
+
+ Save
+
+
+ Cancel
+
+
+
+
+ );
+}
diff --git a/www/src/components/Table/Settings/index.tsx b/src/components/Table/Settings/index.tsx
similarity index 63%
rename from www/src/components/Table/Settings/index.tsx
rename to src/components/Table/Settings/index.tsx
index fedfbda92..3fd3c8731 100644
--- a/www/src/components/Table/Settings/index.tsx
+++ b/src/components/Table/Settings/index.tsx
@@ -2,16 +2,16 @@ import { useState } from "react";
import SettingsMenu from "./Menu";
//import Webhooks from "./Webhooks";
export default function Settings() {
- const [modal, setModal] = useState("");
- return (
- <>
-
- {/*
+
+ {/* {
setModal("");
}}
/> */}
- >
- );
+ >
+ );
}
diff --git a/src/components/Table/Skeleton/HeaderRowSkeleton.tsx b/src/components/Table/Skeleton/HeaderRowSkeleton.tsx
new file mode 100644
index 000000000..ab2050206
--- /dev/null
+++ b/src/components/Table/Skeleton/HeaderRowSkeleton.tsx
@@ -0,0 +1,34 @@
+import { Stack, Skeleton, Button } from "@material-ui/core";
+import AddColumnIcon from "assets/icons/AddColumn";
+
+const NUM_CELLS = 5;
+
+export default function HeaderRowSkeleton() {
+ return (
+
+ {new Array(NUM_CELLS + 1).fill(undefined).map((_, i) => (
+
+ ))}
+
+
+ }>
+ Add Column
+
+
+
+ );
+}
diff --git a/src/components/Table/Skeleton/TableHeaderSkeleton.tsx b/src/components/Table/Skeleton/TableHeaderSkeleton.tsx
new file mode 100644
index 000000000..f0a8ef29f
--- /dev/null
+++ b/src/components/Table/Skeleton/TableHeaderSkeleton.tsx
@@ -0,0 +1,48 @@
+import { Stack, Button } from "@material-ui/core";
+import Skeleton from "@material-ui/core/Skeleton";
+import AddRowIcon from "assets/icons/AddRow";
+
+import { TABLE_HEADER_HEIGHT } from "components/Table/TableHeader";
+
+const ButtonSkeleton = (props) => (
+
+);
+
+export default function TableHeaderSkeleton() {
+ return (
+
+
+ }>
+ Add Row
+
+
+
+
+
+
+ }>
+ Hide
+
+
+
+ }>
+ Filter
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/components/Table/TableHeader/Export/Download.tsx b/src/components/Table/TableHeader/Export/Download.tsx
new file mode 100644
index 000000000..2bf0e0c24
--- /dev/null
+++ b/src/components/Table/TableHeader/Export/Download.tsx
@@ -0,0 +1,205 @@
+import { useState, useContext } from "react";
+import { saveAs } from "file-saver";
+
+import _get from "lodash/get";
+import _find from "lodash/find";
+import _sortBy from "lodash/sortBy";
+import { isString } from "lodash";
+import MultiSelect from "@antlerengineering/multiselect";
+import JSZip from "jszip";
+
+import {
+ DialogActions,
+ Button,
+ TextField,
+ FormControlLabel,
+ Checkbox,
+} from "@material-ui/core";
+
+import { SnackContext } from "contexts/SnackContext";
+import { useRowyContext } from "contexts/RowyContext";
+
+import { FieldType } from "constants/fields";
+import { hasDataTypes } from "components/fields";
+
+const DOWNLOADABLE_COLUMNS = [FieldType.image, FieldType.file];
+const LABEL_COLUMNS = hasDataTypes(["string", "number"]);
+
+const download = (url) => fetch(url).then((resp) => resp.blob());
+
+const selectedColumnsFilesReducer = (doc: any, labelColumns: any[]) => (
+ accumulator: any,
+ currentColumn: any
+) => {
+ const files = _get(doc, currentColumn.key);
+ if (!files || files.length === 0) return accumulator;
+ return [
+ ...accumulator,
+ ...files.map((file, index) => ({
+ ...file,
+ fieldKey: currentColumn.key,
+ name:
+ labelColumns.length === 0
+ ? file.name
+ : `${currentColumn.key}/${labelColumns
+ .map((labelColumn) => {
+ const value = _get(doc, labelColumn.key);
+ return value && typeof value === "string"
+ ? value.replace(/[^a-zA-Z ]/g, "")
+ : "";
+ })
+ .join("_")}${
+ files.length === 1 ? "" : `_${index}`
+ }.${file.name.split(".").pop()}`,
+ })),
+ ];
+};
+
+export default function Export({ query, closeModal }) {
+ const { tableState } = useRowyContext();
+ const snackContext = useContext(SnackContext);
+
+ const [columns, setColumns] = useState([]);
+ const [labelColumnsEnabled, setLabelColumnsEnabled] = useState(false);
+ const [labelColumns, setLabelColumns] = useState([]);
+ const [packageName, setPackageName] = useState(tableState?.tablePath);
+
+ const handleClose = () => {
+ closeModal();
+ setColumns([]);
+ };
+
+ const handleChange = (setState) => (keys: string[]) =>
+ setState(
+ keys
+ .map((key) => _find(tableState!.columns, ["key", key]))
+ .filter((x) => !!x)
+ );
+
+ const handleDownload = async () => {
+ handleClose();
+ snackContext.open({
+ variant: "progress",
+ message: "Preparing file. Download will start shortly",
+ });
+ let querySnapshot = await query.get();
+ let docs = querySnapshot.docs.map((doc) => doc.data());
+ const files = docs
+ .map((doc: any) =>
+ columns.reduce(selectedColumnsFilesReducer(doc, labelColumns), [])
+ )
+ .reduce((acc, row) => [...acc, ...row], []);
+ var zip = new JSZip();
+ let completedCount = 0;
+ const downloads = files.map((file) =>
+ download(file.downloadURL).then((blob: any) => {
+ zip.file(file.name, blob, { base64: true });
+ completedCount++;
+ snackContext.open({
+ variant: "progress",
+ message: "Downloading",
+ });
+ snackContext.setProgress({
+ value: completedCount,
+ target: files.length,
+ });
+ })
+ );
+
+ await Promise.all(downloads);
+ zip
+ .generateAsync({ type: "blob" })
+ .then((content) => saveAs(content, `${packageName}.zip`));
+ snackContext.open({
+ variant: "success",
+ message: "Download completed successfully",
+ duration: 2000,
+ });
+ };
+ return (
+ <>
+ x.key)}
+ onChange={handleChange(setColumns)}
+ options={(typeof tableState!.columns === "object" &&
+ !Array.isArray(tableState!.columns)
+ ? _sortBy(Object.values(tableState!.columns), ["index"]).filter(
+ (column: any) =>
+ isString(column?.name) &&
+ isString(column?.key) &&
+ DOWNLOADABLE_COLUMNS.includes(column.type)
+ )
+ : []
+ ).map((column: any) => ({ label: column.name, value: column.key }))}
+ label="Columns to Export"
+ labelPlural="columns"
+ TextFieldProps={{
+ helperText: "Only File and Image columns are downloadable",
+ }}
+ multiple
+ selectAll
+ />
+
+ setPackageName(e.target.value)}
+ />
+
+ setLabelColumnsEnabled(e.target.checked)}
+ name="labelColumnsEnabled"
+ />
+ }
+ label="Replace file names with table values"
+ />
+
+ x.key)}
+ onChange={handleChange(setLabelColumns)}
+ options={(typeof tableState!.columns === "object" &&
+ !Array.isArray(tableState!.columns)
+ ? _sortBy(Object.values(tableState!.columns), ["index"]).filter(
+ (column: any) =>
+ isString(column?.name) &&
+ isString(column?.key) &&
+ LABEL_COLUMNS.includes(column.type)
+ )
+ : []
+ ).map((column: any) => ({ label: column.name, value: column.key }))}
+ label="Column Values to Include in File Names"
+ labelPlural="columns"
+ TextFieldProps={{
+ autoFocus: true,
+ helperText:
+ labelColumns.length === 0
+ ? `Use original file name`
+ : `eg. column/${labelColumns.map((c) => c.key).join("_")}.jpeg`,
+ }}
+ multiple
+ selectAll
+ />
+
+
+
+
+ Cancel
+
+
+ Download
+
+
+ >
+ );
+}
diff --git a/src/components/Table/TableHeader/Export/Export.tsx b/src/components/Table/TableHeader/Export/Export.tsx
new file mode 100644
index 000000000..eaf4e4185
--- /dev/null
+++ b/src/components/Table/TableHeader/Export/Export.tsx
@@ -0,0 +1,213 @@
+import { useState, useContext } from "react";
+import { parse as json2csv } from "json2csv";
+import { saveAs } from "file-saver";
+
+import _get from "lodash/get";
+import _find from "lodash/find";
+import _sortBy from "lodash/sortBy";
+import { isString } from "lodash";
+import MultiSelect from "@antlerengineering/multiselect";
+
+import { Button, DialogActions } from "@material-ui/core";
+
+import { SnackContext } from "contexts/SnackContext";
+import { useRowyContext } from "contexts/RowyContext";
+
+import { FieldType } from "constants/fields";
+import { getFieldProp } from "components/fields";
+
+const selectedColumnsJsonReducer = (doc: any) => (
+ accumulator: any,
+ currentColumn: any
+) => {
+ const value = _get(doc, currentColumn.key);
+ return {
+ ...accumulator,
+ [currentColumn.key]: value,
+ };
+};
+
+const selectedColumnsCsvReducer = (doc: any) => (
+ accumulator: any,
+ currentColumn: any
+) => {
+ const value = _get(doc, currentColumn.key);
+ const formatter = getFieldProp("csvExportFormatter", currentColumn.type);
+ if (formatter) {
+ return {
+ ...accumulator,
+ [currentColumn.name]: value ? formatter(value, currentColumn.config) : "",
+ };
+ }
+ // TODO: move to field csvExportFormatter
+ switch (currentColumn.type) {
+ case FieldType.multiSelect:
+ return {
+ ...accumulator,
+ [currentColumn.name]: value ? value.join() : "",
+ };
+ case FieldType.file:
+ case FieldType.image:
+ return {
+ ...accumulator,
+ [currentColumn.name]: value
+ ? value
+ .map((item: { downloadURL: string }) => item.downloadURL)
+ .join()
+ : "",
+ };
+ case FieldType.connectTable:
+ return {
+ ...accumulator,
+ [currentColumn.name]:
+ value && Array.isArray(value)
+ ? value
+ .map((item: any) =>
+ currentColumn.config.primaryKeys.reduce(
+ (labelAccumulator: string, currentKey: any) =>
+ `${labelAccumulator} ${item.snapshot[currentKey]}`,
+ ""
+ )
+ )
+ .join()
+ : "",
+ };
+ case FieldType.checkbox:
+ return {
+ ...accumulator,
+ [currentColumn.name]:
+ typeof value === "boolean" ? (value ? "YES" : "NO") : "",
+ };
+ case FieldType.dateTime:
+ case FieldType.date:
+ return {
+ ...accumulator,
+ [currentColumn.name]: value && value["toDate"] ? value.toDate() : "",
+ };
+ case FieldType.action:
+ return {
+ ...accumulator,
+ [currentColumn.name]: value && value.status ? value.status : "",
+ };
+ default:
+ return {
+ ...accumulator,
+ [currentColumn.name]: value ? value : "",
+ };
+ }
+};
+
+export default function Export({ query, closeModal }) {
+ const { tableState } = useRowyContext();
+ const snackContext = useContext(SnackContext);
+
+ const [columns, setColumns] = useState([]);
+ const [exportType, setExportType] = useState<"csv" | "json">("csv");
+
+ const handleClose = () => {
+ closeModal();
+ setColumns([]);
+ };
+
+ const handleChange = (keys: string[]) =>
+ setColumns(
+ keys
+ .map((key) => _find(tableState!.columns, ["key", key]))
+ .filter((x) => !!x)
+ );
+
+ const handleExport = async () => {
+ handleClose();
+ snackContext.open({
+ variant: "info",
+ message: "Preparing file. Download will start shortly",
+ duration: 5000,
+ });
+ let querySnapshot = await query.get();
+ let docs = querySnapshot.docs.map((doc) => ({
+ id: doc.ref.id,
+ ...doc.data(),
+ }));
+
+ const fileName = `${tableState?.tablePath!}-${new Date().toISOString()}.${exportType}`;
+ switch (exportType) {
+ case "csv":
+ const csvData = docs.map((doc: any) =>
+ columns.reduce(selectedColumnsCsvReducer(doc), {})
+ );
+ const csv = json2csv(csvData);
+ const csvBlob = new Blob([csv], {
+ type: `text/${exportType};charset=utf-8`,
+ });
+ saveAs(csvBlob, fileName);
+ break;
+ case "json":
+ const jsonData = docs.map((doc: any) =>
+ columns.reduce(selectedColumnsJsonReducer(doc), { id: doc.id })
+ );
+ const jsonBlob = new Blob([JSON.stringify(jsonData)], {
+ type: `text/${exportType};charset=utf-8`,
+ });
+ saveAs(jsonBlob, fileName);
+ break;
+ default:
+ break;
+ }
+ };
+ return (
+ <>
+ x.key)}
+ onChange={handleChange}
+ options={(typeof tableState!.columns === "object" &&
+ !Array.isArray(tableState!.columns)
+ ? _sortBy(Object.values(tableState!.columns), ["index"]).filter(
+ (column: any) => isString(column?.name) && isString(column?.key)
+ )
+ : []
+ ).map((column: any) => ({ label: column.name, value: column.key }))}
+ label="Columns to Export"
+ labelPlural="columns"
+ TextFieldProps={{
+ autoFocus: true,
+ helperText: "Files and images will be added as URLs",
+ }}
+ multiple
+ selectAll
+ />
+
+ {
+ if (v) {
+ setExportType(v as "csv" | "json");
+ }
+ }}
+ multiple={false}
+ searchable={false}
+ clearable={false}
+ TextFieldProps={{ helperText: "Encoding: UTF-8" }}
+ />
+
+
+
+
+ Cancel
+
+
+ Export
+
+
+ >
+ );
+}
diff --git a/src/components/Table/TableHeader/Export/index.tsx b/src/components/Table/TableHeader/Export/index.tsx
new file mode 100644
index 000000000..baea11b6c
--- /dev/null
+++ b/src/components/Table/TableHeader/Export/index.tsx
@@ -0,0 +1,145 @@
+import { useState, useMemo } from "react";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { DialogContentText, Tab, Divider } from "@material-ui/core";
+import TabContext from "@material-ui/lab/TabContext";
+import TabList from "@material-ui/lab/TabList";
+import TabPanel from "@material-ui/lab/TabPanel";
+
+import TableHeaderButton from "../TableHeaderButton";
+import ExportIcon from "assets/icons/Export";
+
+import Modal from "components/Modal";
+import ExportDetails from "./Export";
+import DownloadDetails from "./Download";
+
+import { useRowyContext } from "contexts/RowyContext";
+import { db } from "../../../../firebase";
+import { isCollectionGroup } from "utils/fns";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ paper: {
+ [theme.breakpoints.up("sm")]: {
+ maxWidth: 440,
+ height: 610,
+ },
+ },
+
+ tabs: {
+ marginLeft: "calc(var(--dialog-spacing) * -1)",
+ marginRight: "calc(var(--dialog-spacing) * -1)",
+ marginTop: theme.spacing(1),
+ },
+ tab: { minWidth: 0 },
+ divider: {
+ margin: "-1px calc(var(--dialog-spacing) * -1) 0",
+ },
+
+ tabPanel: {
+ marginTop: "var(--dialog-contents-spacing)",
+ marginBottom: "calc(var(--dialog-spacing) * -1)",
+ padding: 0,
+
+ flexGrow: 1,
+ display: "flex",
+ flexDirection: "column",
+ height:
+ "calc(100% - var(--dialog-contents-spacing) + var(--dialog-spacing))",
+
+ "& > * + *": { marginTop: "var(--dialog-contents-spacing)" },
+ "&[hidden]": { display: "none" },
+ },
+ })
+);
+
+export default function Export() {
+ const classes = useStyles();
+ const [open, setOpen] = useState(false);
+ const [mode, setMode] = useState<"Export" | "Download">("Export");
+ const { tableState } = useRowyContext();
+
+ const query: any = useMemo(() => {
+ let _query = isCollectionGroup()
+ ? db.collectionGroup(tableState?.tablePath!)
+ : db.collection(tableState?.tablePath!);
+ // add filters
+ tableState?.filters.forEach((filter) => {
+ _query = _query.where(
+ filter.key,
+ filter.operator as firebase.default.firestore.WhereFilterOp,
+ filter.value
+ );
+ });
+ // optional order results
+ if (tableState?.orderBy) {
+ tableState?.orderBy?.forEach((orderBy) => {
+ _query = _query.orderBy(orderBy.key, orderBy.direction);
+ });
+ }
+ return _query.limit(10000);
+ }, [tableState?.tablePath, tableState?.orderBy, tableState?.filters]);
+
+ const handleClose = () => {
+ setOpen(false);
+ setMode("Export");
+ };
+
+ return (
+ <>
+ setOpen(true)}
+ icon={ }
+ />
+
+ {open && (
+
+
+
+ {(tableState?.filters && tableState?.filters.length !== 0) ||
+ (tableState?.orderBy && tableState?.orderBy.length !== 0)
+ ? "The filters and sorting applied to the table will be used in the export."
+ : "No filters or sorting will be applied on the exported data."}
+
+
+ setMode(v)}
+ indicatorColor="primary"
+ textColor="primary"
+ variant="fullWidth"
+ aria-label="Modal tabs"
+ action={(actions) =>
+ setTimeout(() => actions?.updateIndicator(), 200)
+ }
+ >
+
+
+
+
+ >
+ }
+ >
+
+
+
+
+
+
+
+
+
+ )}
+ >
+ );
+}
diff --git a/src/components/Table/TableHeader/Extensions/ExtensionList.tsx b/src/components/Table/TableHeader/Extensions/ExtensionList.tsx
new file mode 100644
index 000000000..b2f0d6af9
--- /dev/null
+++ b/src/components/Table/TableHeader/Extensions/ExtensionList.tsx
@@ -0,0 +1,220 @@
+import { useState, useRef } from "react";
+import { format, formatRelative } from "date-fns";
+
+import {
+ Stack,
+ ButtonBase,
+ List,
+ ListItem,
+ ListItemText,
+ Avatar,
+ Button,
+ IconButton,
+ Menu,
+ MenuItem,
+ Switch,
+ Tooltip,
+ Typography,
+} from "@material-ui/core";
+import AddIcon from "@material-ui/icons/Add";
+import ExtensionIcon from "assets/icons/Extension";
+import DuplicateIcon from "@material-ui/icons/ContentCopy";
+import EditIcon from "@material-ui/icons/Edit";
+import DeleteIcon from "@material-ui/icons/DeleteForever";
+
+import EmptyState from "components/EmptyState";
+import { extensionTypes, IExtension, IExtensionType } from "./utils";
+
+export interface IExtensionListProps {
+ extensions: IExtension[];
+ handleAddExtension: (type: IExtensionType) => void;
+ handleUpdateActive: (index: number, active: boolean) => void;
+ handleDuplicate: (index: number) => void;
+ handleEdit: (index: number) => void;
+ handleDelete: (index: number) => void;
+}
+
+export default function ExtensionList({
+ extensions,
+ handleAddExtension,
+ handleUpdateActive,
+ handleDuplicate,
+ handleEdit,
+ handleDelete,
+}: IExtensionListProps) {
+ const [anchorEl, setAnchorEl] = useState(null);
+ const addButtonRef = useRef(null);
+
+ const activeExtensionCount = extensions.filter(
+ (extension) => extension.active
+ ).length;
+
+ const handleAddButton = () => {
+ setAnchorEl(addButtonRef.current);
+ };
+
+ const handleChooseAddType = (type: IExtensionType) => {
+ handleClose();
+ handleAddExtension(type);
+ };
+
+ const handleClose = () => {
+ setAnchorEl(null);
+ };
+
+ return (
+ <>
+
+
+ Extensions ({activeExtensionCount} / {extensions.length})
+
+
+ }
+ onClick={handleAddButton}
+ ref={addButtonRef}
+ >
+ Add Extension…
+
+
+ {extensionTypes.map((type) => (
+ {
+ handleChooseAddType(type);
+ }}
+ >
+ {type}
+
+ ))}
+
+
+
+ {extensions.length === 0 ? (
+
+
+
+ ) : (
+
+ {extensions.map((extensionObject, index) => (
+
+ }
+ secondaryAction={
+
+
+
+
+ handleUpdateActive(index, !extensionObject.active)
+ }
+ inputProps={{ "aria-label": "Activate" }}
+ sx={{ mr: 1 }}
+ />
+
+
+
+ handleDuplicate(index)}
+ >
+
+
+
+
+ handleEdit(index)}
+ >
+
+
+
+
+ handleDelete(index)}
+ sx={{ "&&": { mr: -1.5 } }}
+ >
+
+
+
+
+
+
+ Last updated by {extensionObject.lastEditor.displayName}
+
+ on{" "}
+ {format(extensionObject.lastEditor.lastUpdate, "PPPP")}
+
+ at{" "}
+ {format(extensionObject.lastEditor.lastUpdate, "pppp")}
+ >
+ }
+ >
+
+
+ {formatRelative(
+ extensionObject.lastEditor.lastUpdate,
+ new Date()
+ )}
+
+
+
+
+
+ }
+ />
+ ))}
+
+ )}
+ >
+ );
+}
diff --git a/src/components/Table/TableHeader/Extensions/ExtensionMigration.tsx b/src/components/Table/TableHeader/Extensions/ExtensionMigration.tsx
new file mode 100644
index 000000000..b6d87132f
--- /dev/null
+++ b/src/components/Table/TableHeader/Extensions/ExtensionMigration.tsx
@@ -0,0 +1,156 @@
+import { useState } from "react";
+import firebase from "firebase/app";
+
+import { Button, Link, Typography } from "@material-ui/core";
+import LoadingButton from "@material-ui/lab/LoadingButton";
+import DownloadIcon from "@material-ui/icons/FileDownloadOutlined";
+import OpenInNewIcon from "@material-ui/icons/OpenInNew";
+import GoIcon from "@material-ui/icons/ChevronRight";
+
+import Modal from "components/Modal";
+import { useRowyContext } from "contexts/RowyContext";
+import { useAppContext } from "contexts/AppContext";
+import { sparkToExtensionObjects } from "./utils";
+import WIKI_LINKS from "constants/wikiLinks";
+
+export interface IExtensionMigrationProps {
+ handleClose: () => void;
+ handleUpgradeComplete: () => void;
+}
+
+export default function ExtensionMigration({
+ handleClose,
+ handleUpgradeComplete,
+}: IExtensionMigrationProps) {
+ const appContext = useAppContext();
+ const { tableState, tableActions } = useRowyContext();
+
+ const [isSaved, setIsSaved] = useState(false);
+ const [isUpgrading, setIsUpgrading] = useState(false);
+
+ const currentEditor = () => ({
+ displayName: appContext?.currentUser?.displayName ?? "Unknown user",
+ photoURL: appContext?.currentUser?.photoURL ?? "",
+ lastUpdate: Date.now(),
+ });
+
+ const downloadSparkFile = () => {
+ const tablePathTokens =
+ tableState?.tablePath?.split("/").filter(function (_, i) {
+ // replace IDs with dash that appears at even indexes
+ return i % 2 === 0;
+ }) ?? [];
+ const tablePath = tablePathTokens.join("-");
+
+ // https://medium.com/front-end-weekly/text-file-download-in-react-a8b28a580c0d
+ const element = document.createElement("a");
+ const file = new Blob([tableState?.config.sparks ?? ""], {
+ type: "text/plain;charset=utf-8",
+ });
+ element.href = URL.createObjectURL(file);
+ element.download = `sparks-${tablePath}.ts`;
+ document.body.appendChild(element);
+ element.click();
+ setIsSaved(true);
+ };
+
+ const upgradeToExtensions = () => {
+ setIsUpgrading(true);
+ const extensionObjects = sparkToExtensionObjects(
+ tableState?.config.sparks ?? "[]",
+ currentEditor()
+ );
+ console.log(extensionObjects);
+ tableActions?.table.updateConfig("extensionObjects", extensionObjects);
+ tableActions?.table.updateConfig(
+ "sparks",
+ firebase.firestore.FieldValue.delete()
+ );
+ setTimeout(handleUpgradeComplete, 500);
+ };
+
+ return (
+
+
+
+ It looks like you have Sparks configured for this table.
+
+
+ Sparks have been revamped to Extensions, with a brand new UI. Your
+ existing Sparks are not compatible with this change, but you can
+ migrate your Sparks to Extensions.
+
+
+
+
+
+ 1. Back Up Existing Sparks
+
+
+ Back up your existing Sparks to a .ts file.
+
+ }
+ style={{ width: "100%" }}
+ >
+ Save Sparks
+
+
+
+
+
+ 2. Migrate Sparks to Extensions
+
+
+
+ After the upgrade, Sparks will be removed from this table. You may
+ need to make manual changes to your Extensions code.
+
+
+
+ Read the Extensions documentation
+
+
+
+ }
+ style={{ width: "100%" }}
+ >
+ Migrate to Extensions
+
+
+ >
+ }
+ />
+ );
+}
diff --git a/src/components/Table/TableHeader/Extensions/ExtensionModal.tsx b/src/components/Table/TableHeader/Extensions/ExtensionModal.tsx
new file mode 100644
index 000000000..263511a46
--- /dev/null
+++ b/src/components/Table/TableHeader/Extensions/ExtensionModal.tsx
@@ -0,0 +1,539 @@
+import { useState } from "react";
+import _isEqual from "lodash/isEqual";
+import useStateRef from "react-usestateref";
+
+import {
+ styled,
+ Button,
+ Checkbox,
+ Divider,
+ FormControl,
+ FormControlLabel,
+ FormGroup,
+ FormLabel,
+ Grid,
+ IconButton,
+ Switch,
+ Stack,
+ Tab,
+ TextField,
+ Typography,
+} from "@material-ui/core";
+import TabContext from "@material-ui/lab/TabContext";
+import TabList from "@material-ui/lab/TabList";
+import TabPanel from "@material-ui/lab/TabPanel";
+import AddIcon from "@material-ui/icons/AddBox";
+import DeleteIcon from "@material-ui/icons/RemoveCircle";
+
+import Modal, { IModalProps } from "components/Modal";
+import CodeEditor from "../../editors/CodeEditor";
+import CodeEditorHelper from "components/CodeEditorHelper";
+
+import { useConfirmation } from "components/ConfirmationDialog";
+import { useRowyContext } from "contexts/RowyContext";
+
+import { IExtension, triggerTypes } from "./utils";
+import WIKI_LINKS from "constants/wikiLinks";
+
+const additionalVariables = [
+ {
+ key: "change",
+ description:
+ "you can pass in field name to change.before.get() or change.after.get() to get changes",
+ },
+ {
+ key: "triggerType",
+ description: "triggerType indicates the type of the extension invocation",
+ },
+ {
+ key: "fieldTypes",
+ description:
+ "fieldTypes is a map of all fields and its corresponding Rowy column type",
+ },
+ {
+ key: "extensionConfig",
+ description: "the configuration object of this extension",
+ },
+];
+
+const StyledTabPanel = styled(TabPanel)({
+ flexGrow: 1,
+
+ overflowY: "auto",
+ margin: "0 calc(var(--dialog-spacing) * -1) 0 !important",
+ padding: "var(--dialog-spacing) var(--dialog-spacing) 0",
+
+ "&[hidden]": { display: "none" },
+
+ display: "flex",
+ flexDirection: "column",
+});
+
+export interface IExtensionModalProps {
+ handleClose: IModalProps["onClose"];
+ handleAdd: (extensionObject: IExtension) => void;
+ handleUpdate: (extensionObject: IExtension) => void;
+ mode: "add" | "update";
+ extensionObject: IExtension;
+}
+
+export default function ExtensionModal({
+ handleClose,
+ handleAdd,
+ handleUpdate,
+ mode,
+ extensionObject: initialObject,
+}: IExtensionModalProps) {
+ const { requestConfirmation } = useConfirmation();
+ const [extensionObject, setExtensionObject] = useState(
+ initialObject
+ );
+ const [tab, setTab] = useState("triggersRequirements");
+ const [validation, setValidation, validationRef] = useStateRef({
+ condition: true,
+ extensionBody: true,
+ });
+ const [, setConditionEditorActive, conditionEditorActiveRef] = useStateRef(
+ false
+ );
+ const [, setBodyEditorActive, bodyEditorActiveRef] = useStateRef(false);
+ const { tableState } = useRowyContext();
+ const columns = Object.keys(tableState?.columns ?? {});
+ const edited = !_isEqual(initialObject, extensionObject);
+
+ const handleAddOrUpdate = () => {
+ switch (mode) {
+ case "add":
+ handleAdd(extensionObject);
+ return;
+ case "update":
+ handleUpdate(extensionObject);
+ return;
+ }
+ };
+
+ return (
+
+
+
+ {
+ setExtensionObject({
+ ...extensionObject,
+ name: event.target.value,
+ });
+ }}
+ />
+
+
+
+
+ setExtensionObject({
+ ...extensionObject,
+ active: e.target.checked,
+ })
+ }
+ size="medium"
+ />
+ }
+ label={`Extension is ${
+ !extensionObject.active ? "de" : ""
+ }activated`}
+ />
+
+
+
+
+
+
+
+
+ setTab(val)}
+ variant="fullWidth"
+ centered
+ style={{
+ marginTop: 0,
+ marginLeft: "calc(var(--dialog-spacing) * -1)",
+ marginRight: "calc(var(--dialog-spacing) * -1)",
+ }}
+ >
+
+
+
+
+
+
+
+
+
+
+ Triggers
+
+
+ Select a trigger that runs your extension code. Selected
+ actions on any cells will trigger the extension.
+
+
+
+ {triggerTypes.map((trigger) => (
+ {
+ if (
+ extensionObject.triggers.includes(trigger)
+ ) {
+ setExtensionObject({
+ ...extensionObject,
+ triggers: extensionObject.triggers.filter(
+ (t) => t !== trigger
+ ),
+ });
+ } else {
+ setExtensionObject({
+ ...extensionObject,
+ triggers: [
+ ...extensionObject.triggers,
+ trigger,
+ ],
+ });
+ }
+ }}
+ />
+ }
+ />
+ ))}
+
+
+
+
+
+
+
+ Required Fields (optional)
+
+
+ Optionally, select the fields that are required for the
+ extension to be triggered for a row.
+
+
+ *": { flexShrink: 0 },
+ }}
+ >
+ {columns.sort().map((field) => (
+ {
+ if (
+ extensionObject.requiredFields.includes(field)
+ ) {
+ setExtensionObject({
+ ...extensionObject,
+ requiredFields: extensionObject.requiredFields.filter(
+ (t) => t !== field
+ ),
+ });
+ } else {
+ setExtensionObject({
+ ...extensionObject,
+ requiredFields: [
+ ...extensionObject.requiredFields,
+ field,
+ ],
+ });
+ }
+ }}
+ />
+ }
+ />
+ ))}
+
+ {extensionObject.requiredFields.map((trigger, index) => {
+ const isRowyColumn = columns.includes(trigger);
+ if (isRowyColumn) {
+ return null;
+ }
+
+ return (
+
+ {
+ setExtensionObject({
+ ...extensionObject,
+ requiredFields: extensionObject.requiredFields.filter(
+ (t) => t !== trigger
+ ),
+ });
+ }}
+ >
+
+
+ {
+ setExtensionObject({
+ ...extensionObject,
+ requiredFields: extensionObject.requiredFields.map(
+ (value, i) =>
+ i === index ? event.target.value : value
+ ),
+ });
+ }}
+ />
+
+ );
+ })}
+
+
+ }
+ onClick={() => {
+ setExtensionObject({
+ ...extensionObject,
+ requiredFields: [
+ ...extensionObject.requiredFields,
+ "",
+ ],
+ });
+ }}
+ >
+ Add Firestore Field
+
+
+
+
+
+
+
+
+
+ Conditions
+
+
+ {
+ setExtensionObject({
+ ...extensionObject,
+ conditions: newValue,
+ });
+ }}
+ onValideStatusUpdate={({ isValid }) => {
+ if (!conditionEditorActiveRef.current) {
+ return;
+ }
+ setValidation({
+ ...validationRef.current,
+ condition: isValid,
+ });
+ console.log(validationRef.current);
+ }}
+ diagnosticsOptions={{
+ noSemanticValidation: false,
+ noSyntaxValidation: false,
+ noSuggestionDiagnostics: true,
+ }}
+ onMount={() => {
+ setConditionEditorActive(true);
+ }}
+ onUnmount={() => {
+ setConditionEditorActive(false);
+ }}
+ />
+
+
+
+
+
+
+
+ Extension Body
+
+
+ {
+ setExtensionObject({
+ ...extensionObject,
+ extensionBody: newValue,
+ });
+ }}
+ onValidStatusUpdate={({ isValid }) => {
+ if (!bodyEditorActiveRef.current) {
+ return;
+ }
+ setValidation({
+ ...validationRef.current,
+ extensionBody: isValid,
+ });
+ console.log(validationRef.current);
+ }}
+ diagnosticsOptions={{
+ noSemanticValidation: false,
+ noSyntaxValidation: false,
+ noSuggestionDiagnostics: true,
+ }}
+ onMount={() => {
+ setBodyEditorActive(true);
+ }}
+ onUnmount={() => {
+ setBodyEditorActive(false);
+ }}
+ />
+
+
+
+
+ >
+ }
+ actions={{
+ primary: {
+ children: mode === "add" ? "Add" : "Update",
+ disabled: !edited || !extensionObject.name.length,
+ onClick: () => {
+ let warningMessage;
+ if (!validation.condition && !validation.extensionBody) {
+ warningMessage = "Condition and extension body are not valid";
+ } else if (!validation.condition) {
+ warningMessage = "Condition is not valid";
+ } else if (!validation.extensionBody) {
+ warningMessage = "Extension body is not valid";
+ }
+
+ if (warningMessage) {
+ requestConfirmation({
+ title: "Validation Failed",
+ body: `${warningMessage}. Continue?`,
+ confirm: "Yes, I know what I’m doing",
+ cancel: "No, I’ll fix the errors",
+ handleConfirm: handleAddOrUpdate,
+ });
+ } else {
+ handleAddOrUpdate();
+ }
+ },
+ },
+ }}
+ />
+ );
+}
diff --git a/src/components/Table/TableHeader/Extensions/index.tsx b/src/components/Table/TableHeader/Extensions/index.tsx
new file mode 100644
index 000000000..30e7c7dce
--- /dev/null
+++ b/src/components/Table/TableHeader/Extensions/index.tsx
@@ -0,0 +1,291 @@
+import { useState } from "react";
+import _isEqual from "lodash/isEqual";
+import { db } from "../../../../firebase";
+
+import { Breadcrumbs, Typography, Button } from "@material-ui/core";
+
+import TableHeaderButton from "../TableHeaderButton";
+import ExtensionIcon from "assets/icons/Extension";
+import Modal from "components/Modal";
+import ExtensionList from "./ExtensionList";
+import ExtensionModal from "./ExtensionModal";
+import ExtensionMigration from "./ExtensionMigration";
+
+import { useRowyContext } from "contexts/RowyContext";
+import { useAppContext } from "contexts/AppContext";
+import { useConfirmation } from "components/ConfirmationDialog";
+import { useSnackContext } from "contexts/SnackContext";
+import { useSnackLogContext } from "contexts/SnackLogContext";
+
+import {
+ serialiseExtension,
+ emptyExtensionObject,
+ IExtension,
+ IExtensionType,
+} from "./utils";
+import WIKI_LINKS from "constants/wikiLinks";
+
+export default function ExtensionsEditor() {
+ const snack = useSnackContext();
+ const { tableState, tableActions } = useRowyContext();
+ const appContext = useAppContext();
+ const { requestConfirmation } = useConfirmation();
+ const currentextensionObjects = (tableState?.config.extensionObjects ??
+ []) as IExtension[];
+ const [localExtensionsObjects, setLocalExtensionsObjects] = useState(
+ currentextensionObjects
+ );
+ const [openExtensionList, setOpenExtensionList] = useState(false);
+ const [openMigrationGuide, setOpenMigrationGuide] = useState(false);
+ const [extensionModal, setExtensionModal] = useState<{
+ mode: "add" | "update";
+ extensionObject: IExtension;
+ index?: number;
+ } | null>(null);
+ const snackLogContext = useSnackLogContext();
+ const edited = !_isEqual(currentextensionObjects, localExtensionsObjects);
+
+ const tablePathTokens =
+ tableState?.tablePath?.split("/").filter(function (_, i) {
+ // replace IDs with dash that appears at even indexes
+ return i % 2 === 0;
+ }) ?? [];
+
+ const handleOpen = () => {
+ if (tableState?.config.sparks) {
+ // migration is required
+ console.log("Extension migration required.");
+ setOpenMigrationGuide(true);
+ } else {
+ setOpenExtensionList(true);
+ }
+ };
+
+ const handleClose = () => {
+ if (edited) {
+ requestConfirmation({
+ title: "Discard Changes",
+ body: "You will lose changes you have made to extensions",
+ confirm: "Discard",
+ handleConfirm: () => {
+ setLocalExtensionsObjects(currentextensionObjects);
+ setOpenExtensionList(false);
+ },
+ });
+ } else {
+ setOpenExtensionList(false);
+ }
+ };
+
+ const handleSaveExtensions = () => {
+ tableActions?.table.updateConfig(
+ "extensionObjects",
+ localExtensionsObjects
+ );
+ setOpenExtensionList(false);
+ };
+
+ const handleSaveDeploy = async () => {
+ handleSaveExtensions();
+
+ // compile extension objects into ft-build readable extension string
+ const serialisedExtension = serialiseExtension(localExtensionsObjects);
+ tableActions?.table.updateConfig("extensions", serialisedExtension);
+
+ const settingsDoc = await db.doc("/_rowy_/settings").get();
+ const buildUrl = settingsDoc.get("buildUrl");
+ if (!buildUrl) {
+ snack.open({
+ message: "Cloud Run Trigger URL not set.",
+ variant: "error",
+ action: (
+
+ Setup Guide
+
+ ),
+ });
+ }
+
+ // request GCP build
+ const userTokenInfo = await appContext?.currentUser?.getIdTokenResult();
+ const userToken = userTokenInfo?.token;
+ try {
+ snackLogContext.requestSnackLog();
+ const response = await fetch(buildUrl, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({
+ configPath: tableState?.config.tableConfig.path,
+ token: userToken,
+ }),
+ });
+ const data = await response.json();
+ } catch (e) {
+ console.error(e);
+ }
+ };
+
+ const handleAddExtension = (extensionObject: IExtension) => {
+ setLocalExtensionsObjects([...localExtensionsObjects, extensionObject]);
+ setExtensionModal(null);
+ };
+
+ const handleUpdateExtension = (extensionObject: IExtension) => {
+ setLocalExtensionsObjects(
+ localExtensionsObjects.map((extension, index) => {
+ if (index === extensionModal?.index) {
+ return {
+ ...extensionObject,
+ lastEditor: currentEditor(),
+ };
+ } else {
+ return extension;
+ }
+ })
+ );
+ setExtensionModal(null);
+ };
+
+ const handleUpdateActive = (index: number, active: boolean) => {
+ setLocalExtensionsObjects(
+ localExtensionsObjects.map((extensionObject, i) => {
+ if (i === index) {
+ return {
+ ...extensionObject,
+ active,
+ lastEditor: currentEditor(),
+ };
+ } else {
+ return extensionObject;
+ }
+ })
+ );
+ };
+
+ const handleDuplicate = (index: number) => {
+ setLocalExtensionsObjects([
+ ...localExtensionsObjects,
+ {
+ ...localExtensionsObjects[index],
+ name: `${localExtensionsObjects[index].name} (duplicate)`,
+ active: false,
+ lastEditor: currentEditor(),
+ },
+ ]);
+ };
+
+ const handleEdit = (index: number) => {
+ setExtensionModal({
+ mode: "update",
+ extensionObject: localExtensionsObjects[index],
+ index,
+ });
+ };
+
+ const handleDelete = (index: number) => {
+ requestConfirmation({
+ title: `Delete ${localExtensionsObjects[index].name}?`,
+ body: "This extension will be permanently deleted.",
+ confirm: "Confirm",
+ handleConfirm: () => {
+ setLocalExtensionsObjects(
+ localExtensionsObjects.filter((_, i) => i !== index)
+ );
+ },
+ });
+ };
+
+ const currentEditor = () => ({
+ displayName: appContext?.currentUser?.displayName ?? "Unknown user",
+ photoURL: appContext?.currentUser?.photoURL ?? "",
+ lastUpdate: Date.now(),
+ });
+
+ return (
+ <>
+ }
+ />
+
+ {openExtensionList && !!tableState && (
+
+
+ {tablePathTokens.map((pathToken) => {
+ return {pathToken} ;
+ })}
+
+ {
+ setExtensionModal({
+ mode: "add",
+ extensionObject: emptyExtensionObject(
+ type,
+ currentEditor()
+ ),
+ });
+ }}
+ handleUpdateActive={handleUpdateActive}
+ handleEdit={handleEdit}
+ handleDuplicate={handleDuplicate}
+ handleDelete={handleDelete}
+ />
+ >
+ }
+ actions={{
+ primary: {
+ children: "Save & Deploy",
+ onClick: handleSaveDeploy,
+ disabled: !edited,
+ },
+ secondary: {
+ children: "Save",
+ onClick: handleSaveExtensions,
+ disabled: !edited,
+ },
+ }}
+ />
+ )}
+
+ {extensionModal && (
+ {
+ setExtensionModal(null);
+ }}
+ handleAdd={handleAddExtension}
+ handleUpdate={handleUpdateExtension}
+ mode={extensionModal.mode}
+ extensionObject={extensionModal.extensionObject}
+ />
+ )}
+
+ {openMigrationGuide && (
+ {
+ setOpenMigrationGuide(false);
+ }}
+ handleUpgradeComplete={() => {
+ setOpenMigrationGuide(false);
+ setOpenExtensionList(true);
+ }}
+ />
+ )}
+ >
+ );
+}
diff --git a/src/components/Table/TableHeader/Extensions/utils.ts b/src/components/Table/TableHeader/Extensions/utils.ts
new file mode 100644
index 000000000..768b1877b
--- /dev/null
+++ b/src/components/Table/TableHeader/Extensions/utils.ts
@@ -0,0 +1,278 @@
+type IExtensionType =
+ | "task"
+ | "docSync"
+ | "historySnapshot"
+ | "algoliaIndex"
+ | "meiliIndex"
+ | "bigqueryIndex"
+ | "slackMessage"
+ | "sendgridEmail"
+ | "apiCall"
+ | "twilioMessage";
+
+type IExtensionTrigger = "create" | "update" | "delete";
+
+interface IExtensionEditor {
+ displayName: string;
+ photoURL: string;
+ lastUpdate: number;
+}
+
+interface IExtension {
+ // rowy meta fields
+ name: string;
+ active: boolean;
+ lastEditor: IExtensionEditor;
+
+ // ft build fields
+ triggers: IExtensionTrigger[];
+ type: IExtensionType;
+ requiredFields: string[];
+ extensionBody: string;
+ conditions: string;
+}
+
+const triggerTypes: IExtensionTrigger[] = ["create", "update", "delete"];
+
+const extensionTypes: IExtensionType[] = [
+ "task",
+ "docSync",
+ "historySnapshot",
+ "algoliaIndex",
+ "meiliIndex",
+ "bigqueryIndex",
+ "slackMessage",
+ "sendgridEmail",
+ "apiCall",
+ "twilioMessage",
+];
+
+const extensionBodyTemplate = {
+ task: `const extensionBody: TaskBody = async({row, db, change, ref}) => {
+ // task extensions are very flexible you can do anything from updating other documents in your database, to making an api request to 3rd party service.
+
+ // eg:
+ // const got = require('got');
+ // const {body} = await got.post('https://httpbin.org/anything', {
+ // json: {
+ // hello: 'world'
+ // },
+ // responseType: 'json'
+ // });
+
+ // console.log(body.data);
+ // => {hello: 'world'}
+
+ console.log("Task Extension completed.")
+}`,
+ docSync: `const extensionBody: DocSyncBody = async({row, db, change, ref}) => {
+ // feel free to add your own code logic here
+
+ return ({
+ fieldsToSync: [], // a list of string of column names
+ row: row, // object of data to sync, usually the row itself
+ targetPath: "", // fill in the path here
+ })
+}`,
+ historySnapshot: `const extensionBody: HistorySnapshotBody = async({row, db, change, ref}) => {
+ // feel free to add your own code logic here
+
+ return ({
+ trackedFields: [], // a list of string of column names
+ })
+}`,
+ algoliaIndex: `const extensionBody: AlgoliaIndexBody = async({row, db, change, ref}) => {
+ // feel free to add your own code logic here
+
+ return ({
+ fieldsToSync: [], // a list of string of column names
+ row: row, // object of data to sync, usually the row itself
+ index: "", // algolia index to sync to
+ objectID: ref.id, // algolia object ID, ref.id is one possible choice
+ })
+}`,
+ meiliIndex: `const extensionBody: MeiliIndexBody = async({row, db, change, ref}) => {
+ // feel free to add your own code logic here
+
+ return({
+ fieldsToSync: [], // a list of string of column names
+ row: row, // object of data to sync, usually the row itself
+ index: "", // algolia index to sync to
+ objectID: ref.id, // algolia object ID, ref.id is one possible choice
+ })
+}`,
+ bigqueryIndex: `const extensionBody: BigqueryIndexBody = async({row, db, change, ref}) => {
+ // feel free to add your own code logic here
+
+ return ({
+ fieldsToSync: [], // a list of string of column names
+ row: row, // object of data to sync, usually the row itself
+ index: "", // algolia index to sync to
+ objectID: ref.id, // algolia object ID, ref.id is one possible choice
+ })
+}`,
+ slackMessage: `const extensionBody: SlackMessageBody = async({row, db, change, ref}) => {
+ // feel free to add your own code logic here
+
+ return ({
+ channels: [], // a list of slack channel IDs in string
+ blocks: [], // the blocks parameter to pass in to slack api
+ text: "", // the text parameter to pass in to slack api
+ attachments: [], // the attachments parameter to pass in to slack api
+ })
+}`,
+ sendgridEmail: `const extensionBody: SendgridEmailBody = async({row, db, change, ref}) => {
+ // feel free to add your own code logic here
+
+ return ({
+ from: "Name", // send from field
+ personalizations: [
+ {
+ to: [{ name: "", email: "" }], // recipient
+ dynamic_template_data: {
+ }, // template parameters
+ },
+ ],
+ template_id: "", // sendgrid template ID
+ categories: [], // helper info to categorise sendgrid emails
+ })
+}`,
+ apiCall: `const extensionBody: ApiCallBody = async({row, db, change, ref}) => {
+ // feel free to add your own code logic here
+
+ return ({
+ body: "",
+ url: "",
+ method: "",
+ callback: ()=>{},
+ })
+}`,
+ twilioMessage: `const extensionBody: TwilioMessageBody = async({row, db, change, ref}) => {
+ // feel free to add your own code logic here
+
+ return ({
+ from:"",
+ to:"",
+ body:"Hi there!"
+ })
+}`,
+};
+
+function emptyExtensionObject(
+ type: IExtensionType,
+ user: IExtensionEditor
+): IExtension {
+ return {
+ name: "Untitled extension",
+ active: false,
+ triggers: [],
+ type,
+ extensionBody: extensionBodyTemplate[type] ?? extensionBodyTemplate["task"],
+ requiredFields: [],
+ conditions: `const condition: Condition = async({row, change}) => {
+ // feel free to add your own code logic here
+ return true;
+}`,
+ lastEditor: user,
+ };
+}
+
+/* Convert extension objects into a single ft-build readable string */
+function serialiseExtension(extensions: IExtension[]): string {
+ const serialisedExtension =
+ "[" +
+ extensions
+ .filter((extension) => extension.active)
+ .map(
+ (extension) => `{
+ name: "${extension.name}",
+ type: "${extension.type}",
+ triggers: [${extension.triggers
+ .map((trigger) => `"${trigger}"`)
+ .join(", ")}],
+ conditions: ${extension.conditions
+ .replace(/^.*:\s*Condition\s*=/, "")
+ .replace(/\s*;\s*$/, "")},
+ requiredFields: [${extension.requiredFields
+ .map((field) => `"${field}"`)
+ .join(", ")}],
+ extensionBody: ${extension.extensionBody
+ .replace(/^.*:\s*\w*Body\s*=/, "")
+ .replace(/\s*;\s*$/, "")}
+ }`
+ )
+ .join(",") +
+ "]";
+ console.log("serialisedExtension", serialisedExtension);
+ return serialisedExtension;
+}
+
+function sparkToExtensionObjects(
+ sparkConfig: string,
+ user: IExtensionEditor
+): IExtension[] {
+ const parseString2Array = (str: string): string[] => {
+ return str
+ .trim()
+ .replace(/\[|\]/g, "")
+ .split(",")
+ .map((x) => x.trim().replace(/'/g, ""));
+ };
+ const oldSparks = sparkConfig.replace(/"/g, "'");
+ const sparkTypes = oldSparks
+ .match(/(?<=type:).*(?=,)/g)
+ ?.map((x) => x.trim().replace(/'/g, ""));
+ const triggers = oldSparks
+ .match(/(?<=triggers:).*(?=,)/g)
+ ?.map((x) => parseString2Array(x));
+ const shouldRun = oldSparks
+ .match(/(?<=shouldRun:).*(?=,)/g)
+ ?.map((x) => x.trim());
+ const requiredFields = oldSparks
+ .match(/(?<=requiredFields:).*(?=,)/g)
+ ?.map((x) => parseString2Array(x));
+ const splitSparks = oldSparks.split(`type:`);
+ const sparks = sparkTypes?.map((x, index) => {
+ const sparkBody = splitSparks[index + 1]
+ ?.split("sparkBody:")[1]
+ ?.trim()
+ .slice(0, -1);
+ const _triggers = triggers?.[index];
+ const _shouldRun = shouldRun?.[index];
+ const _requiredFields = requiredFields?.[index];
+ return {
+ type: x,
+ triggers: _triggers,
+ shouldRun: _shouldRun,
+ requiredFields: _requiredFields,
+ sparkBody,
+ };
+ });
+ const extensionObjects = sparks?.map(
+ (spark, index): IExtension => {
+ return {
+ // rowy meta fields
+ name: `Migrated spark ${index}`,
+ active: true,
+ lastEditor: user,
+
+ // ft build fields
+ triggers: (spark.triggers ?? []) as IExtensionTrigger[],
+ type: spark.type as IExtensionType,
+ requiredFields: spark.requiredFields ?? [],
+ extensionBody: spark.sparkBody,
+ conditions: spark.shouldRun ?? "",
+ };
+ }
+ );
+ return extensionObjects ?? [];
+}
+
+export {
+ serialiseExtension,
+ extensionTypes,
+ triggerTypes,
+ emptyExtensionObject,
+ sparkToExtensionObjects,
+};
+export type { IExtension, IExtensionType, IExtensionEditor };
diff --git a/src/components/Table/TableHeader/ImportCsv.tsx b/src/components/Table/TableHeader/ImportCsv.tsx
new file mode 100644
index 000000000..1c8548af4
--- /dev/null
+++ b/src/components/Table/TableHeader/ImportCsv.tsx
@@ -0,0 +1,305 @@
+import React, { useState, useCallback } from "react";
+import clsx from "clsx";
+import parse from "csv-parse";
+import { useDropzone } from "react-dropzone";
+import { useDebouncedCallback } from "use-debounce";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import {
+ Button,
+ Popover,
+ PopoverProps as MuiPopoverProps,
+ Grid,
+ Typography,
+ TextField,
+ FormHelperText,
+} from "@material-ui/core";
+
+import Tab from "@material-ui/core/Tab";
+import TabContext from "@material-ui/lab/TabContext";
+import TabList from "@material-ui/lab/TabList";
+import TabPanel from "@material-ui/lab/TabPanel";
+
+import TableHeaderButton from "./TableHeaderButton";
+import ImportIcon from "assets/icons/Import";
+
+import FileUploadIcon from "assets/icons/FileUpload";
+import CheckIcon from "@material-ui/icons/CheckCircle";
+
+import ImportCsvWizard, {
+ IImportCsvWizardProps,
+} from "components/Wizards/ImportCsvWizard";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ tabPanel: {
+ padding: theme.spacing(2, 3),
+ width: 400,
+ height: 200,
+ },
+ continueButton: {
+ margin: theme.spacing(-4, "auto", 2),
+ display: "flex",
+ minWidth: 100,
+ },
+
+ dropzone: {
+ height: 137,
+ borderRadius: theme.shape.borderRadius,
+ border: `dashed 2px ${theme.palette.divider}`,
+ backgroundColor: theme.palette.action.input,
+ cursor: "pointer",
+
+ "& svg": { opacity: theme.palette.action.activeOpacity },
+
+ "&:focus": {
+ borderColor: theme.palette.primary.main,
+ color: theme.palette.primary.main,
+ outline: "none",
+ },
+ },
+ error: {
+ "$dropzone&": {
+ borderColor: theme.palette.error.main,
+ color: theme.palette.error.main,
+ },
+ },
+ dropzoneError: { margin: theme.spacing(0.5, 1.5) },
+
+ pasteField: {
+ ...theme.typography.body2,
+ fontFamily: theme.typography.fontFamilyMono,
+ },
+ pasteInput: {
+ whiteSpace: "nowrap",
+ overflow: "auto",
+ },
+ })
+);
+
+export interface IImportCsvProps {
+ render?: (
+ onClick: (event: React.MouseEvent) => void
+ ) => React.ReactNode;
+ PopoverProps?: Partial;
+}
+
+export default function ImportCsv({ render, PopoverProps }: IImportCsvProps) {
+ const classes = useStyles();
+
+ const [open, setOpen] = useState(null);
+ const [tab, setTab] = useState("upload");
+ const [csvData, setCsvData] = useState(
+ null
+ );
+ const [error, setError] = useState("");
+ const validCsv =
+ csvData !== null && csvData?.columns.length > 0 && csvData?.rows.length > 0;
+
+ const handleOpen = (event: React.MouseEvent) =>
+ setOpen(event.currentTarget);
+ const handleClose = () => {
+ setOpen(null);
+ setCsvData(null);
+ setTab("upload");
+ setError("");
+ };
+ const popoverId = open ? "csv-popover" : undefined;
+
+ const parseCsv = (csvString: string) =>
+ parse(csvString, {}, (err, rows) => {
+ if (err) {
+ setError(err.message);
+ } else {
+ const columns = rows.shift() ?? [];
+ if (columns.length === 0) {
+ setError("No columns detected");
+ } else {
+ const mappedRows = rows.map((row) =>
+ row.reduce((a, c, i) => ({ ...a, [columns[i]]: c }), {})
+ );
+ setCsvData({ columns, rows: mappedRows });
+ setError("");
+ }
+ }
+ });
+
+ const onDrop = useCallback(async (acceptedFiles) => {
+ const file = acceptedFiles[0];
+ const reader = new FileReader();
+ reader.onload = (event: any) => parseCsv(event.target.result);
+ reader.readAsText(file);
+ }, []);
+ const { getRootProps, getInputProps, isDragActive } = useDropzone({
+ onDrop,
+ multiple: false,
+ accept: "text/csv",
+ });
+
+ const [handlePaste] = useDebouncedCallback(
+ (value: string) => parseCsv(value),
+ 1000
+ );
+
+ const [loading, setLoading] = useState(false);
+ const [handleUrl] = useDebouncedCallback((value: string) => {
+ setLoading(true);
+ setError("");
+ fetch(value, { mode: "no-cors" })
+ .then((res) => res.text())
+ .then((data) => {
+ parseCsv(data);
+ setLoading(false);
+ })
+ .catch((e) => {
+ setError(e.message);
+ setLoading(false);
+ });
+ }, 1000);
+
+ const [openWizard, setOpenWizard] = useState(false);
+
+ return (
+ <>
+ {render ? (
+ render(handleOpen)
+ ) : (
+ }
+ />
+ )}
+
+
+
+ {
+ setTab(v);
+ setCsvData(null);
+ setError("");
+ }}
+ aria-label="Import CSV method tabs"
+ action={(actions) =>
+ setTimeout(() => actions?.updateIndicator(), 200)
+ }
+ variant="fullWidth"
+ >
+
+
+
+
+
+
+
+
+ {isDragActive ? (
+
+ Drop CSV file here…
+
+ ) : (
+ <>
+
+ {validCsv ? : }
+
+
+
+ {validCsv
+ ? "Valid CSV"
+ : "Click to upload or drop CSV file here"}
+
+
+ >
+ )}
+
+
+ {error && (
+
+ {error}
+
+ )}
+
+
+
+ {
+ if (csvData !== null) setCsvData(null);
+ handlePaste(e.target.value);
+ }}
+ InputProps={{
+ classes: {
+ root: classes.pasteField,
+ input: classes.pasteInput,
+ },
+ }}
+ helperText={error}
+ error={!!error}
+ />
+
+
+
+ {
+ if (csvData !== null) setCsvData(null);
+ handleUrl(e.target.value);
+ }}
+ helperText={loading ? "Fetching CSV…" : error}
+ error={!!error}
+ />
+
+
+
+ setOpenWizard(true)}
+ >
+ Continue
+
+
+
+ {openWizard && csvData && (
+ setOpenWizard(false)}
+ csvData={csvData}
+ />
+ )}
+ >
+ );
+}
diff --git a/src/components/Table/TableHeader/ReExecute.tsx b/src/components/Table/TableHeader/ReExecute.tsx
new file mode 100644
index 000000000..c403c80af
--- /dev/null
+++ b/src/components/Table/TableHeader/ReExecute.tsx
@@ -0,0 +1,78 @@
+import { useState } from "react";
+
+import TableHeaderButton from "./TableHeaderButton";
+import LoopIcon from "@material-ui/icons/Loop";
+
+import { useRowyContext } from "contexts/RowyContext";
+import { db } from "../../../firebase";
+import { isCollectionGroup } from "utils/fns";
+import CircularProgress from "@material-ui/core/CircularProgress";
+
+import { DialogContentText } from "@material-ui/core";
+
+import Modal from "components/Modal";
+
+export default function ReExecute() {
+ const [open, setOpen] = useState(false);
+ const [updating, setUpdating] = useState(false);
+ const handleClose = () => {
+ setOpen(false);
+ };
+
+ const { tableState } = useRowyContext();
+ const query: any = isCollectionGroup()
+ ? db.collectionGroup(tableState?.tablePath!)
+ : db.collection(tableState?.tablePath!);
+
+ const handleConfirm = async () => {
+ setUpdating(true);
+ const _forcedUpdateAt = new Date();
+ const querySnapshot = await query.get();
+ const docs = [...querySnapshot.docs];
+ while (docs.length) {
+ const batch = db.batch();
+ const temp = docs.splice(0, 499);
+ temp.forEach((doc) => {
+ batch.update(doc.ref, { _forcedUpdateAt });
+ });
+ await batch.commit();
+ }
+ setTimeout(() => {
+ setUpdating(false);
+ setOpen(false);
+ }, 3000); // give time to for ft function to run
+ };
+
+ return (
+ <>
+ setOpen(true)}
+ icon={ }
+ />
+
+ {open && (
+ ,
+ disabled: updating,
+ },
+ secondary: {
+ children: "Cancel",
+ onClick: handleClose,
+ },
+ }}
+ />
+ )}
+ >
+ );
+}
diff --git a/src/components/Table/TableHeader/RowHeight.tsx b/src/components/Table/TableHeader/RowHeight.tsx
new file mode 100644
index 000000000..a620a468e
--- /dev/null
+++ b/src/components/Table/TableHeader/RowHeight.tsx
@@ -0,0 +1,70 @@
+import { useRef, useState } from "react";
+
+import {
+ useTheme,
+ TextField,
+ ListSubheader,
+ MenuItem,
+} from "@material-ui/core";
+import RowHeightIcon from "assets/icons/RowHeight";
+
+import TableHeaderButton from "./TableHeaderButton";
+import { useRowyContext } from "contexts/RowyContext";
+
+export default function RowHeight() {
+ const theme = useTheme();
+
+ const buttonRef = useRef(null);
+
+ const [open, setOpen] = useState(false);
+ const handleOpen = () => setOpen(true);
+ const handleClose = () => setOpen(false);
+
+ const { tableActions, tableState } = useRowyContext();
+
+ const rowHeight = tableState?.config.rowHeight;
+ const updateConfig = tableActions?.table.updateConfig;
+
+ console.log(buttonRef);
+
+ return (
+ <>
+ }
+ onClick={handleOpen}
+ ref={buttonRef}
+ />
+
+ {
+ if (updateConfig) updateConfig("rowHeight", event.target.value);
+ }}
+ style={{ display: "none" }}
+ SelectProps={{
+ open: open,
+ onOpen: handleOpen,
+ onClose: handleClose,
+ MenuProps: {
+ anchorEl: buttonRef.current,
+ anchorOrigin: { vertical: "bottom", horizontal: "right" },
+ transformOrigin: { vertical: "top", horizontal: "right" },
+ style: { zIndex: theme.zIndex.tooltip },
+ },
+ }}
+ label="Row Height"
+ id="row-height-select"
+ >
+ Row Height
+ Short
+ Tall
+ Grande
+ Venti
+ Trenta
+
+ >
+ );
+}
diff --git a/src/components/Table/TableHeader/TableHeaderButton.tsx b/src/components/Table/TableHeader/TableHeaderButton.tsx
new file mode 100644
index 000000000..ed575dbc9
--- /dev/null
+++ b/src/components/Table/TableHeader/TableHeaderButton.tsx
@@ -0,0 +1,30 @@
+import { forwardRef } from "react";
+import { Tooltip, Button, ButtonProps } from "@material-ui/core";
+
+export interface ITableHeaderButtonProps extends Partial {
+ title: string;
+ icon: React.ReactNode;
+}
+
+export const TableHeaderButton = forwardRef(function TableHeaderButton_(
+ { title, icon, ...props }: ITableHeaderButtonProps,
+ ref: React.Ref
+) {
+ return (
+
+
+ {icon}
+
+
+ );
+});
+
+export default TableHeaderButton;
diff --git a/src/components/Table/TableHeader/TableLogs.tsx b/src/components/Table/TableHeader/TableLogs.tsx
new file mode 100644
index 000000000..90fb75527
--- /dev/null
+++ b/src/components/Table/TableHeader/TableLogs.tsx
@@ -0,0 +1,581 @@
+import React, { useEffect, useRef, useState } from "react";
+import useRouter from "hooks/useRouter";
+import useCollection from "hooks/useCollection";
+import { useRowyContext } from "contexts/RowyContext";
+import useStateRef from "react-usestateref";
+import { db } from "../../../firebase";
+import { useSnackLogContext } from "contexts/SnackLogContext";
+import { isCollectionGroup } from "utils/fns";
+
+import _throttle from "lodash/throttle";
+import { format } from "date-fns";
+import moment from "moment";
+
+import {
+ Chip,
+ Stack,
+ CircularProgress,
+ Typography,
+ Box,
+ Tabs,
+ Tab,
+ IconButton,
+ Button,
+} from "@material-ui/core";
+import Modal from "components/Modal";
+import { makeStyles, createStyles } from "@material-ui/styles";
+import LogsIcon from "assets/icons/CloudLogs";
+import SuccessIcon from "@material-ui/icons/CheckCircle";
+import FailIcon from "@material-ui/icons/Cancel";
+import ExpandIcon from "@material-ui/icons/ExpandLess";
+import CollapseIcon from "@material-ui/icons/ExpandMore";
+import OpenIcon from "@material-ui/icons/OpenInNew";
+import CloseIcon from "@material-ui/icons/Close";
+import TableHeaderButton from "./TableHeaderButton";
+import Ansi from "ansi-to-react";
+import EmptyState from "components/EmptyState";
+
+import PropTypes from "prop-types";
+import routes from "constants/routes";
+import { DATE_TIME_FORMAT } from "constants/dates";
+
+function a11yProps(index) {
+ return {
+ id: `vertical-tab-${index}`,
+ "aria-controls": `vertical-tabpanel-${index}`,
+ };
+}
+
+const isTargetInsideBox = (target, box) => {
+ const targetRect = target.getBoundingClientRect();
+ const boxRect = box.getBoundingClientRect();
+ return targetRect.y < boxRect.y + boxRect.height;
+};
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ toolbarStatusIcon: {
+ fontSize: 12,
+
+ position: "absolute",
+ bottom: 2,
+ right: 5,
+
+ backgroundColor: theme.palette.background.paper,
+ boxShadow: `0 0 0 1px ${theme.palette.background.paper}`,
+ borderRadius: "50%",
+ },
+
+ root: {
+ display: "flex",
+ height: "100%",
+ },
+
+ logPanel: {
+ width: "100%",
+ backgroundColor: "#1E1E1E",
+ },
+ logPanelProgress: {
+ marginLeft: "2em",
+ marginTop: "1em",
+ },
+ logEntryWrapper: {
+ overflowY: "scroll",
+ maxHeight: "100%",
+ },
+ logNumber: {
+ float: "left",
+ width: "2em",
+ textAlign: "right",
+ paddingRight: "1em",
+ },
+ logEntry: {
+ lineBreak: "anywhere",
+ paddingLeft: "2em",
+ whiteSpace: "break-spaces",
+ userSelect: "text",
+ },
+ logTypeInfo: {
+ color: "green",
+ },
+ logTypeError: {
+ color: "red",
+ },
+ logFont: {
+ ...theme.typography.body2,
+ fontFamily: theme.typography.fontFamilyMono,
+ // TODO:
+ color: "#CCC",
+
+ "& code": {
+ fontFamily: theme.typography.fontFamilyMono,
+ },
+ },
+
+ snackLog: {
+ position: "absolute",
+ left: 40,
+ bottom: 40,
+ backgroundColor: "#282829",
+ width: "min(40vw, 640px)",
+ padding: theme.spacing(1, 2, 2, 2),
+ borderRadius: 4,
+ zIndex: 1,
+ height: 300,
+ transition: "height 300ms ease-out",
+ },
+ snackLogExpanded: {
+ height: "calc(100% - 300px)",
+ },
+
+ whiteText: {
+ color: "white",
+ },
+ })
+);
+
+LogPanel.propTypes = {
+ logs: PropTypes.array,
+ status: PropTypes.string,
+ index: PropTypes.any.isRequired,
+ value: PropTypes.any.isRequired,
+};
+
+function LogRow({ logRecord, index }) {
+ const classes = useStyles();
+
+ return (
+
+
+ {index}
+
+
+
+ {moment(logRecord.timestamp).format("LTS")}
+
+ {" "}
+
+ {logRecord.log
+ .replaceAll("\\n", "\n")
+ .replaceAll("\\t", "\t")
+ .replaceAll("\\", "")}
+
+
+
+ );
+}
+
+function LogPanel(props) {
+ const { logs, status, value, index, ...other } = props;
+ const classes = useStyles();
+
+ // useStateRef is necessary to resolve the state syncing issue
+ // https://stackoverflow.com/a/63039797/12208834
+ const [liveStreaming, setLiveStreaming, liveStreamingStateRef] = useStateRef(
+ true
+ );
+ const liveStreamingRef = useRef();
+ const isActive = value === index;
+
+ const handleScroll = _throttle(() => {
+ const target = document.querySelector("#live-stream-target");
+ const scrollBox = document.querySelector("#live-stream-scroll-box");
+ const liveStreamTargetVisible = isTargetInsideBox(target, scrollBox);
+ if (liveStreamTargetVisible !== liveStreamingStateRef.current) {
+ setLiveStreaming(liveStreamTargetVisible);
+ }
+ }, 500);
+
+ const scrollToLive = () => {
+ const liveStreamTarget = document.querySelector("#live-stream-target");
+ liveStreamTarget?.scrollIntoView?.({
+ behavior: "smooth",
+ });
+ };
+
+ useEffect(() => {
+ if (liveStreaming && isActive && status === "BUILDING") {
+ if (!liveStreamingRef.current) {
+ scrollToLive();
+ } else {
+ setTimeout(scrollToLive, 100);
+ }
+ }
+ }, [logs, value]);
+
+ useEffect(() => {
+ if (isActive) {
+ const liveStreamScrollBox = document.querySelector(
+ "#live-stream-scroll-box"
+ );
+ liveStreamScrollBox!.addEventListener("scroll", () => {
+ handleScroll();
+ });
+ }
+ }, [value]);
+
+ return (
+
+ {value === index && (
+
+ {logs?.map((log, index) => {
+ return ;
+ })}
+
+ {status === "BUILDING" && (
+
+ )}
+
+
+
+ )}
+
+ );
+}
+
+function SnackLog({ log, onClose, onOpenPanel }) {
+ const logs = log?.fullLog;
+ const status = log?.status;
+ const classes = useStyles();
+ const [expanded, setExpanded] = useState(false);
+ const [liveStreaming, setLiveStreaming, liveStreamingStateRef] = useStateRef(
+ true
+ );
+ const liveStreamingRef = useRef();
+
+ const handleScroll = _throttle(() => {
+ const target = document.querySelector("#live-stream-target-snack");
+ const scrollBox = document.querySelector("#live-stream-scroll-box-snack");
+ const liveStreamTargetVisible =
+ target && scrollBox && isTargetInsideBox(target, scrollBox);
+ if (liveStreamTargetVisible !== liveStreamingStateRef.current) {
+ setLiveStreaming(liveStreamTargetVisible);
+ }
+ }, 100);
+
+ const scrollToLive = () => {
+ const liveStreamTarget = document.querySelector(
+ "#live-stream-target-snack"
+ );
+ liveStreamTarget?.scrollIntoView?.();
+ };
+
+ useEffect(() => {
+ if (liveStreaming && status === "BUILDING") {
+ if (!liveStreamingRef.current) {
+ scrollToLive();
+ } else {
+ setTimeout(scrollToLive, 500);
+ }
+ }
+ }, [log]);
+
+ useEffect(() => {
+ const liveStreamScrollBox = document.querySelector(
+ "#live-stream-scroll-box-snack"
+ );
+ liveStreamScrollBox!.addEventListener("scroll", () => {
+ handleScroll();
+ });
+ }, []);
+
+ return (
+
+
+
+ {!log && Build Pending... }
+ {log?.status === "SUCCESS" && (
+
+ Build Completed
+
+ )}
+ {log?.status === "FAIL" && (
+
+ Build Failed
+
+ )}
+ {log?.status === "BUILDING" && (
+ Building...
+ )}
+
+
+ setExpanded(!expanded)}
+ >
+ {expanded ? : }
+
+
+
+
+
+
+
+
+
+
+
+ {log && (
+ <>
+ {logs?.map((log, index) => {
+ return ;
+ })}
+
+ {status === "BUILDING" && (
+
+ )}
+
+
+ >
+ )}
+
+
+ );
+}
+
+export default function TableLogs() {
+ const router = useRouter();
+ const { tableState } = useRowyContext();
+
+ const classes = useStyles();
+ const [panalOpen, setPanelOpen] = useState(false);
+ const [buildURLConfigured, setBuildURLConfigured] = useState(true);
+ const [tabIndex, setTabIndex] = React.useState(0);
+ const snackLogContext = useSnackLogContext();
+
+ useEffect(() => {
+ checkBuildURL();
+ }, []);
+
+ const checkBuildURL = async () => {
+ const settingsDoc = await db.doc("/_rowy_/settings").get();
+ const buildUrl = settingsDoc.get("buildUrl");
+ if (!buildUrl) {
+ setBuildURLConfigured(false);
+ }
+ };
+
+ const tableCollection = decodeURIComponent(router.match.params.id);
+ const buildStreamID =
+ "_rowy_/settings/" +
+ `${isCollectionGroup() ? "groupSchema/" : "schema/"}` +
+ tableCollection
+ .split("/")
+ .filter(function (_, i) {
+ // replace IDs with subTables that appears at even indexes
+ return i % 2 === 0;
+ })
+ .join("/subTables/");
+
+ const [collectionState] = useCollection({
+ path: `${buildStreamID}/buildLogs`,
+ orderBy: [{ key: "startTimeStamp", direction: "desc" }],
+ limit: 30,
+ });
+ const latestLog = collectionState?.documents?.[0];
+ const latestStatus = latestLog?.status;
+ const latestActiveLog =
+ latestLog?.startTimeStamp > snackLogContext.latestBuildTimestamp
+ ? latestLog
+ : null;
+
+ const handleTabChange = (event, newValue) => {
+ setTabIndex(newValue);
+ };
+
+ return (
+ <>
+ setPanelOpen(true)}
+ icon={
+ <>
+
+ {latestStatus === "BUILDING" && (
+
+ )}
+ {latestStatus === "SUCCESS" && (
+
+ )}
+ {latestStatus === "FAIL" && (
+
+ )}
+ >
+ }
+ />
+
+ {snackLogContext.isSnackLogOpen && (
+ {
+ setPanelOpen(true);
+ }}
+ />
+ )}
+
+ {panalOpen && !!tableState && (
+ {
+ setPanelOpen(false);
+ }}
+ maxWidth="xl"
+ fullWidth
+ fullHeight
+ title={
+ <>
+ Build Logs
+ >
+ }
+ children={
+ <>
+ {!latestStatus && buildURLConfigured && (
+
+ )}
+ {!latestStatus && !buildURLConfigured && (
+
+
+ Function builder is not currently setup.{" "}
+
+
+ Go to Settings
+
+ >
+ }
+ />
+ )}
+ {latestStatus && (
+
+
+ {collectionState.documents?.map((logEntry, index) => (
+
+ {logEntry.status === "BUILDING" && (
+
+ )}
+ {logEntry.status === "SUCCESS" && }
+ {logEntry.status === "FAIL" && }
+
+
+ {format(
+ logEntry.startTimeStamp,
+ DATE_TIME_FORMAT
+ )}
+
+
+ }
+ {...a11yProps(index)}
+ />
+ ))}
+
+ {collectionState.documents.map((logEntry, index) => (
+
+ ))}
+
+ )}
+ >
+ }
+ />
+ )}
+ >
+ );
+}
diff --git a/src/components/Table/TableHeader/TableSettings.tsx b/src/components/Table/TableHeader/TableSettings.tsx
new file mode 100644
index 000000000..db21b4c92
--- /dev/null
+++ b/src/components/Table/TableHeader/TableSettings.tsx
@@ -0,0 +1,31 @@
+import { useState } from "react";
+
+import TableHeaderButton from "./TableHeaderButton";
+import SettingsIcon from "@material-ui/icons/SettingsOutlined";
+
+import TableSettingsDialog, {
+ TableSettingsDialogModes,
+} from "components/TableSettings";
+import { useRowyContext } from "contexts/RowyContext";
+
+export default function TableSettings() {
+ const [open, setOpen] = useState(false);
+
+ const { tableState } = useRowyContext();
+
+ return (
+ <>
+ setOpen(true)}
+ icon={ }
+ />
+
+ setOpen(false)}
+ mode={open ? TableSettingsDialogModes.update : null}
+ data={open ? tableState?.config.tableConfig.doc : null}
+ />
+ >
+ );
+}
diff --git a/src/components/Table/TableHeader/index.tsx b/src/components/Table/TableHeader/index.tsx
new file mode 100644
index 000000000..7b23cc1cd
--- /dev/null
+++ b/src/components/Table/TableHeader/index.tsx
@@ -0,0 +1,155 @@
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { Stack, Button } from "@material-ui/core";
+
+import { isCollectionGroup } from "utils/fns";
+import AddRowIcon from "assets/icons/AddRow";
+
+import Filters from "../Filters";
+import ImportCSV from "./ImportCsv";
+import Export from "./Export";
+import TableSettings from "./TableSettings";
+import TableLogs from "./TableLogs";
+import HiddenFields from "../HiddenFields";
+import RowHeight from "./RowHeight";
+import Extensions from "./Extensions";
+import ReExecute from "./ReExecute";
+
+import { useAppContext } from "contexts/AppContext";
+import { useRowyContext, rowyUser } from "contexts/RowyContext";
+import { FieldType } from "constants/fields";
+
+export const TABLE_HEADER_HEIGHT = 44;
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: {
+ width: "100%",
+ margin: 0,
+ padding: theme.spacing(0, 2, 1.5, 1),
+ height: TABLE_HEADER_HEIGHT,
+
+ overflowX: "auto",
+ whiteSpace: "nowrap",
+
+ userSelect: "none",
+
+ [theme.breakpoints.down("md")]: {
+ width: "100%",
+ paddingRight: theme.spacing(1),
+ },
+
+ "& > *": { paddingTop: "0 !important" },
+ },
+
+ spacer: { width: theme.spacing(2) },
+ midSpacer: { minWidth: theme.spacing(8) },
+ })
+);
+
+/**
+ * TODO: Make this properly mobile responsive, not just horizontally scrolling
+ */
+export default function TableHeader() {
+ const { currentUser } = useAppContext();
+ const { tableActions, tableState, userClaims } = useRowyContext();
+
+ const hasDerivatives =
+ tableState &&
+ Object.values(tableState.columns)?.filter(
+ (column) => column.type === FieldType.derivative
+ ).length > 0;
+ const hasExtensions =
+ tableState &&
+ tableState.config?.compiledExtension?.replace(/\W/g, "")?.length > 0;
+
+ if (!tableState || !tableState.columns) return null;
+ const { columns } = tableState;
+
+ return (
+ *": { flexShrink: 0 },
+ }}
+ >
+ {!isCollectionGroup() && (
+ /* */
+ {
+ const requiredFields = Object.values(columns)
+ .map((column) => {
+ if (column.config.required) {
+ return column.key;
+ }
+ })
+ .filter((c) => c);
+ const initialVal = Object.values(columns).reduce((acc, column) => {
+ if (column.config?.defaultValue?.type === "static") {
+ return {
+ ...acc,
+ [column.key]: column.config.defaultValue.value,
+ };
+ } else if (column.config?.defaultValue?.type === "null") {
+ return { ...acc, [column.key]: null };
+ } else return acc;
+ }, {});
+ tableActions?.row.add(
+ {
+ ...initialVal,
+ _updatedBy: rowyUser(currentUser),
+ _createdBy: rowyUser(currentUser),
+ },
+ requiredFields
+ );
+ }}
+ variant="contained"
+ color="primary"
+ startIcon={ }
+ // sx={{ pr: 1.5 }}
+ >
+ Add Row
+
+ /*
+
+
+ */
+ )}
+ {/* Spacer */}
+
+
+
+
+ {/* Spacer */}
+ {!isCollectionGroup() && }
+
+ {userClaims?.roles?.includes("ADMIN") && (
+ <>
+ {/* Spacer */}
+
+
+ {(hasDerivatives || hasExtensions) && }
+ >
+ )}
+ {/* Spacer */}
+
+
+ );
+}
diff --git a/src/components/Table/editors/CodeEditor.tsx b/src/components/Table/editors/CodeEditor.tsx
new file mode 100644
index 000000000..728ee24cc
--- /dev/null
+++ b/src/components/Table/editors/CodeEditor.tsx
@@ -0,0 +1,398 @@
+import { useRef, useMemo, useState } from "react";
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { useTheme } from "@material-ui/core/styles";
+import Editor, { useMonaco } from "@monaco-editor/react";
+import { useRowyContext } from "contexts/RowyContext";
+import { FieldType } from "constants/fields";
+import { useEffect } from "react";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ editorWrapper: {
+ position: "relative",
+ minWidth: 400,
+ minHeight: 100,
+ height: "calc(100% - 50px)",
+ border: `1px solid ${theme.palette.divider}`,
+ borderRadius: theme.shape.borderRadius,
+ overflow: "hidden",
+ },
+
+ saveButton: {
+ marginTop: theme.spacing(1),
+ },
+ editor: {
+ // overwrite user-select: none that causes editor not focusable in Safari
+ userSelect: "auto",
+ },
+ })
+);
+
+export default function CodeEditor(props: any) {
+ const {
+ handleChange,
+ extraLibs,
+ height = 400,
+ script,
+ onValideStatusUpdate,
+ diagnosticsOptions,
+ onUnmount,
+ onMount,
+ } = props;
+ const theme = useTheme();
+ const monacoInstance = useMonaco();
+
+ const [initialEditorValue] = useState(script ?? "");
+ const { tableState } = useRowyContext();
+ const classes = useStyles();
+
+ const editorRef = useRef();
+
+ useEffect(() => {
+ return () => {
+ onUnmount?.();
+ };
+ }, []);
+
+ function handleEditorDidMount(_, editor) {
+ editorRef.current = editor;
+ onMount?.();
+ }
+
+ const themeTransformer = (theme: string) => {
+ switch (theme) {
+ case "dark":
+ return "vs-dark";
+ default:
+ return theme;
+ }
+ };
+
+ useMemo(async () => {
+ if (!monacoInstance) {
+ // useMonaco returns a monaco instance but initialisation is done asynchronously
+ // dont execute the logic until the instance is initialised
+ return;
+ }
+
+ const firestoreDefsFile = await fetch(
+ `${process.env.PUBLIC_URL}/firestore.d.ts`
+ );
+ const firebaseAuthDefsFile = await fetch(
+ `${process.env.PUBLIC_URL}/auth.d.ts`
+ );
+ const firebaseStorageDefsFile = await fetch(
+ `${process.env.PUBLIC_URL}/storage.d.ts`
+ );
+ const firestoreDefs = await firestoreDefsFile.text();
+ const firebaseStorageDefs = await firebaseStorageDefsFile.text();
+ const firebaseAuthDefs = (await firebaseAuthDefsFile.text())
+ ?.replace("export", "declare")
+ ?.replace("admin.auth", "adminauth");
+
+ try {
+ monacoInstance.languages.typescript.javascriptDefaults.addExtraLib(
+ firestoreDefs
+ );
+ monacoInstance.languages.typescript.javascriptDefaults.addExtraLib(
+ firebaseAuthDefs
+ );
+ monacoInstance.languages.typescript.javascriptDefaults.addExtraLib(
+ firebaseStorageDefs
+ );
+ monacoInstance.languages.typescript.javascriptDefaults.setDiagnosticsOptions(
+ diagnosticsOptions ?? {
+ noSemanticValidation: true,
+ noSyntaxValidation: false,
+ }
+ );
+ // compiler options
+ monacoInstance.languages.typescript.javascriptDefaults.setCompilerOptions(
+ {
+ target: monacoInstance.languages.typescript.ScriptTarget.ES2020,
+ allowNonTsExtensions: true,
+ }
+ );
+ if (extraLibs) {
+ monacoInstance.languages.typescript.javascriptDefaults.addExtraLib(
+ extraLibs.join("\n"),
+ "ts:filename/extraLibs.d.ts"
+ );
+ }
+ monacoInstance.languages.typescript.javascriptDefaults.addExtraLib(
+ [
+ " /**",
+ " * utility functions",
+ " */",
+ `
+ declare namespace utilFns {
+ /**
+ * Sends out an email through sendGrid
+ */
+ function sendEmail(msg: {
+ from: string;
+ templateId: string;
+ personalizations: { to: string; dynamic_template_data: any }[];
+ }): void {}
+
+ /**
+ * Gets the secret defined in Google Cloud Secret
+ */
+ async function getSecret(name: string, v?: string): any {}
+
+ /**
+ * Async version of forEach
+ */
+ async function asyncForEach(array: any[], callback: Function): void {}
+
+ /**
+ * Generate random ID from numbers and English charactors inlcuding lowercase and uppercase
+ */
+ function generateId(): string {}
+
+ /**
+ * Add an item to an array field
+ */
+ function arrayUnion(val: string): void {}
+
+ /**
+ * Remove an item to an array field
+ */
+ function arrayRemove(val: string): void {}
+
+ /**
+ * Increment a number field
+ */
+ function increment(val: number): void {}
+
+ function hasRequiredFields(requiredFields: string[], data: any): boolean {}
+
+ function hasAnyRole(
+ authorizedRoles: string[],
+ context: functions.https.CallableContext
+ ): boolean {}
+ }
+
+ `,
+ ].join("\n"),
+ "ts:filename/utils.d.ts"
+ );
+
+ const rowDefinition = [
+ ...Object.keys(tableState?.columns!).map((columnKey: string) => {
+ const column = tableState?.columns[columnKey];
+ switch (column.type) {
+ case FieldType.shortText:
+ case FieldType.longText:
+ case FieldType.email:
+ case FieldType.phone:
+ case FieldType.code:
+ return `${columnKey}:string`;
+ case FieldType.singleSelect:
+ const typeString = [
+ ...(column.config?.options?.map((opt) => `"${opt}"`) ?? []),
+ ].join(" | ");
+ return `${columnKey}:${typeString}`;
+ case FieldType.multiSelect:
+ return `${columnKey}:string[]`;
+ case FieldType.checkbox:
+ return `${columnKey}:boolean`;
+ default:
+ return `${columnKey}:any`;
+ }
+ }),
+ ].join(";\n");
+
+ const availableFields = Object.keys(tableState?.columns!)
+ .map((columnKey: string) => `"${columnKey}"`)
+ .join("|\n");
+
+ const extensionsDefinition = `
+ // basic types that are used in all places
+ type Row = {${rowDefinition}};
+ type Field = ${availableFields} | string | object;
+ type Fields = Field[];
+ type Trigger = "create" | "update" | "delete";
+ type Triggers = Trigger[];
+
+ // function types that defines extension body and shuold run
+ type Condition = boolean | ((data: ExtensionContext) => boolean | Promise);
+
+ // the argument that the extension body takes in
+ type ExtensionContext = {
+ row: Row;
+ ref:FirebaseFirestore.DocumentReference;
+ storage:firebasestorage.Storage;
+ db:FirebaseFirestore.Firestore;
+ auth:adminauth.BaseAuth;
+ change: any;
+ triggerType: Triggers;
+ fieldTypes: any;
+ extensionConfig: {
+ label: string;
+ type: sring;
+ triggers: Trigger[];
+ conditions: Condition;
+ requiredFields: string[];
+ extensionBody: any;
+ };
+ utilFns: any;
+ }
+
+ // extension body definition
+ type slackEmailBody = {
+ channels?: string[];
+ text?: string;
+ emails: string[];
+ blocks?: object[];
+ attachments?: any;
+ }
+
+ type slackChannelBody = {
+ channels: string[];
+ text?: string;
+ emails?: string[];
+ blocks?: object[];
+ attachments?: any;
+ }
+
+ type DocSyncBody = (context: ExtensionContext) => Promise<{
+ fieldsToSync: Fields;
+ row: Row;
+ targetPath: string;
+ }>
+
+ type HistorySnapshotBody = (context: ExtensionContext) => Promise<{
+ trackedFields: Fields;
+ }>
+
+ type AlgoliaIndexBody = (context: ExtensionContext) => Promise<{
+ fieldsToSync: Fields;
+ index: string;
+ row: Row;
+ objectID: string;
+ }>
+
+ type MeiliIndexBody = (context: ExtensionContext) => Promise<{
+ fieldsToSync: Fields;
+ index: string;
+ row: Row;
+ objectID: string;
+ }>
+
+ type BigqueryIndexBody = (context: ExtensionContext) => Promise<{
+ fieldsToSync: Fields;
+ index: string;
+ row: Row;
+ objectID: string;
+ }>
+
+ type SlackMessageBody = (context: ExtensionContext) => Promise;
+
+ type SendgridEmailBody = (context: ExtensionContext) => Promise;
+
+ type ApiCallBody = (context: ExtensionContext) => Promise<{
+ body: string;
+ url: string;
+ method: string;
+ callback: any;
+ }>
+
+ type TwilioMessageBody = (context: ExtensionContext) => Promise<{
+ body: string;
+ from: string;
+ to: string;
+ }>
+
+ type TaskBody = (context: ExtensionContext) => Promise
+ `;
+
+ monacoInstance.languages.typescript.javascriptDefaults.addExtraLib(
+ [
+ " /**",
+ " * extensions type configuration",
+ " */",
+ extensionsDefinition,
+ ].join("\n"),
+ "ts:filename/extensions.d.ts"
+ );
+
+ monacoInstance.languages.typescript.javascriptDefaults.addExtraLib(
+ [
+ " declare var require: any;",
+ " declare var Buffer: any;",
+ " const ref:FirebaseFirestore.DocumentReference",
+ " const storage:firebasestorage.Storage",
+ " const db:FirebaseFirestore.Firestore;",
+ " const auth:adminauth.BaseAuth;",
+ "declare class row {",
+ " /**",
+ " * Returns the row fields",
+ " */",
+ ...Object.keys(tableState?.columns!).map((columnKey: string) => {
+ const column = tableState?.columns[columnKey];
+ switch (column.type) {
+ case FieldType.shortText:
+ case FieldType.longText:
+ case FieldType.email:
+ case FieldType.phone:
+ case FieldType.code:
+ return `static ${columnKey}:string`;
+ case FieldType.singleSelect:
+ const typeString = [
+ ...(column.config?.options?.map((opt) => `"${opt}"`) ?? []),
+ // "string",
+ ].join(" | ");
+ return `static ${columnKey}:${typeString}`;
+ case FieldType.multiSelect:
+ return `static ${columnKey}:string[]`;
+ case FieldType.checkbox:
+ return `static ${columnKey}:boolean`;
+ default:
+ return `static ${columnKey}:any`;
+ }
+ }),
+ "}",
+ ].join("\n"),
+ "ts:filename/rowFields.d.ts"
+ );
+ } catch (error) {
+ console.error(
+ "An error occurred during initialization of Monaco: ",
+ error
+ );
+ }
+ }, [tableState?.columns, monacoInstance]);
+
+ function handleEditorValidation(markers) {
+ if (onValideStatusUpdate) {
+ onValideStatusUpdate({
+ isValid: markers.length <= 0,
+ });
+ }
+ }
+
+ return (
+ <>
+
+
+
+ >
+ );
+}
diff --git a/www/src/components/Table/editors/NullEditor.tsx b/src/components/Table/editors/NullEditor.tsx
similarity index 83%
rename from www/src/components/Table/editors/NullEditor.tsx
rename to src/components/Table/editors/NullEditor.tsx
index 3ec5954b6..7add748ad 100644
--- a/www/src/components/Table/editors/NullEditor.tsx
+++ b/src/components/Table/editors/NullEditor.tsx
@@ -16,11 +16,11 @@ import styles from "./styles";
* TODO: fix NullEditor overwriting the formatter component
*/
class NullEditor extends React.Component<
- EditorProps & WithStyles
+ EditorProps & WithStyles
> {
- getInputNode = () => null;
- getValue = () => null;
- render = () => null;
+ getInputNode = () => null;
+ getValue = () => null;
+ render = () => null;
}
export default withStyles(styles)(NullEditor);
diff --git a/src/components/Table/editors/TextEditor.tsx b/src/components/Table/editors/TextEditor.tsx
new file mode 100644
index 000000000..d0b2fee98
--- /dev/null
+++ b/src/components/Table/editors/TextEditor.tsx
@@ -0,0 +1,112 @@
+import { useRef, useLayoutEffect } from "react";
+import { EditorProps } from "react-data-grid";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { TextField } from "@material-ui/core";
+
+import { FieldType } from "constants/fields";
+import { getCellValue } from "utils/fns";
+import { useRowyContext } from "contexts/RowyContext";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: {
+ margin: theme.spacing(0, -1.5),
+ width: `calc(100% + ${theme.spacing(1.5 * 2)})`,
+ height: "100%",
+
+ backgroundColor: theme.palette.background.paper,
+ },
+
+ inputBase: {
+ padding: theme.spacing(0, 1.5),
+ height: "100%",
+ font: "inherit",
+ letterSpacing: "inherit", // Prevent text jumping
+ },
+ input: {
+ paddingBottom: theme.spacing(0.75), // Align baselines
+ letterSpacing: "inherit", // Prevent text jumping
+ height: "100%", // Stop text clipping
+ },
+ })
+);
+
+export default function TextEditor({ row, column }: EditorProps) {
+ const { updateCell } = useRowyContext();
+ const classes = useStyles();
+
+ const type = (column as any).config?.renderFieldType ?? (column as any).type;
+
+ const cellValue = getCellValue(row, column.key);
+ const defaultValue =
+ type === FieldType.percentage && typeof cellValue === "number"
+ ? cellValue * 100
+ : cellValue;
+
+ const inputRef = useRef(null);
+
+ useLayoutEffect(() => {
+ return () => {
+ const newValue = inputRef.current?.value;
+ if (newValue !== undefined && updateCell) {
+ if (type === FieldType.number || type === FieldType.percentage) {
+ updateCell(row.ref, column.key, Number(newValue));
+ } else {
+ updateCell(row.ref, column.key, newValue);
+ }
+ }
+ };
+ }, []);
+
+ let inputType = "text";
+ switch (type) {
+ case FieldType.email:
+ inputType = "email";
+ break;
+ case FieldType.phone:
+ inputType = "tel";
+ break;
+ case FieldType.url:
+ inputType = "url";
+ break;
+ case FieldType.number:
+ case FieldType.percentage:
+ inputType = "number";
+ break;
+
+ default:
+ break;
+ }
+
+ const { maxLength } = (column as any).config;
+
+ return (
+ {
+ if (e.key === "ArrowLeft" || e.key === "ArrowRight") {
+ e.stopPropagation();
+ }
+
+ if (e.key === "Escape") {
+ (e.target as any).value = defaultValue;
+ }
+ }}
+ />
+ );
+}
diff --git a/www/src/components/Table/editors/styles.ts b/src/components/Table/editors/styles.ts
similarity index 62%
rename from www/src/components/Table/editors/styles.ts
rename to src/components/Table/editors/styles.ts
index ea265fd29..5631828c7 100644
--- a/www/src/components/Table/editors/styles.ts
+++ b/src/components/Table/editors/styles.ts
@@ -1,9 +1,9 @@
import { createStyles } from "@material-ui/core";
export const styles = createStyles({
- "@global": {
- ".rdg-editor-container": { display: "none" },
- },
+ "@global": {
+ ".rdg-editor-container": { display: "none" },
+ },
});
export default styles;
diff --git a/src/components/Table/editors/withSideDrawerEditor.tsx b/src/components/Table/editors/withSideDrawerEditor.tsx
new file mode 100644
index 000000000..5545ff4f1
--- /dev/null
+++ b/src/components/Table/editors/withSideDrawerEditor.tsx
@@ -0,0 +1,40 @@
+import React, { useEffect } from "react";
+import { EditorProps } from "react-data-grid";
+import { useRowyContext } from "contexts/RowyContext";
+import { IHeavyCellProps } from "components/fields/types";
+
+import { getCellValue } from "utils/fns";
+
+/**
+ * Allow the cell to be editable, but disable react-data-grid’s default
+ * text editor to show. Opens the side drawer in the appropriate position.
+ *
+ * Displays the current HeavyCell or HeavyCell since it overwrites cell contents.
+ *
+ * Use for cells that do not support any type of in-cell editing.
+ */
+export default function withSideDrawerEditor(
+ HeavyCell?: React.ComponentType
+) {
+ return function SideDrawerEditor(props: EditorProps) {
+ const { row, column } = props;
+ const { sideDrawerRef } = useRowyContext();
+
+ useEffect(() => {
+ if (!sideDrawerRef?.current?.open && sideDrawerRef?.current?.setOpen)
+ sideDrawerRef?.current?.setOpen(true);
+ }, [column]);
+
+ return HeavyCell ? (
+ {}}
+ disabled={props.column.editable === false}
+ />
+ ) : null;
+ };
+}
diff --git a/src/components/Table/formatters/FinalColumn.tsx b/src/components/Table/formatters/FinalColumn.tsx
new file mode 100644
index 000000000..9b77d1a41
--- /dev/null
+++ b/src/components/Table/formatters/FinalColumn.tsx
@@ -0,0 +1,108 @@
+import { useContext } from "react";
+import { FormatterProps } from "react-data-grid";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { Grid, Tooltip, IconButton } from "@material-ui/core";
+import CopyCellsIcon from "assets/icons/CopyCells";
+import DeleteIcon from "@material-ui/icons/DeleteForever";
+
+import { SnackContext } from "contexts/SnackContext";
+import { useConfirmation } from "components/ConfirmationDialog/Context";
+import { useRowyContext } from "contexts/RowyContext";
+import useKeyPress from "hooks/useKeyPress";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ "@global": {
+ ".final-column-cell": {
+ ".rdg .rdg-cell&": {
+ backgroundColor: "var(--header-background-color)",
+ borderColor: "var(--header-background-color)",
+ color: theme.palette.text.disabled,
+ },
+
+ ".rdg-row:hover &": { color: theme.palette.text.primary },
+ },
+ },
+ })
+);
+
+export default function FinalColumn({ row }: FormatterProps) {
+ useStyles();
+
+ const { requestConfirmation } = useConfirmation();
+ const { tableActions } = useRowyContext();
+ const shiftPress = useKeyPress("Shift");
+ const snack = useContext(SnackContext);
+
+ const handleDelete = async () => tableActions?.row.delete(row.id);
+ return (
+
+
+
+ {
+ const clonedRow = { ...row };
+ // remove metadata
+ delete clonedRow.ref;
+ delete clonedRow.rowHeight;
+ delete clonedRow._updatedAt;
+ delete clonedRow._updatedBy;
+ delete clonedRow._createdAt;
+ Object.keys(clonedRow).forEach((key) => {
+ if (clonedRow[key] === undefined) {
+ delete clonedRow[key];
+ }
+ });
+ if (tableActions) tableActions?.row.add(clonedRow);
+ }}
+ aria-label="Duplicate row"
+ >
+
+
+
+
+
+
+
+ {shiftPress ? (
+
+
+
+ ) : (
+ //
+ {
+ requestConfirmation({
+ title: "Delete Row",
+ body: "Are you sure you want to delete this row?",
+ confirm: "Delete",
+ handleConfirm: handleDelete,
+ });
+ }}
+ aria-label="Delete row"
+ >
+
+
+ //
+ )}
+
+
+
+ );
+}
diff --git a/src/components/Table/index.tsx b/src/components/Table/index.tsx
new file mode 100644
index 000000000..ab22aea89
--- /dev/null
+++ b/src/components/Table/index.tsx
@@ -0,0 +1,260 @@
+import React, { useEffect, useRef, useMemo, useState } from "react";
+import _orderBy from "lodash/orderBy";
+
+import _find from "lodash/find";
+import _difference from "lodash/difference";
+import _get from "lodash/get";
+
+import { DndProvider } from "react-dnd";
+import { HTML5Backend } from "react-dnd-html5-backend";
+
+import "react-data-grid/dist/react-data-grid.css";
+import DataGrid, {
+ Column,
+ SelectColumn as _SelectColumn,
+} from "react-data-grid";
+
+import Loading from "components/Loading";
+import TableHeader from "./TableHeader";
+import ColumnHeader from "./ColumnHeader";
+import ColumnMenu from "./ColumnMenu";
+import FinalColumnHeader from "./FinalColumnHeader";
+import FinalColumn from "./formatters/FinalColumn";
+import BulkActions from "./BulkActions";
+
+import { getFieldProp } from "components/fields";
+import { FieldType } from "constants/fields";
+import { formatSubTableName } from "utils/fns";
+
+import { useAppContext } from "contexts/AppContext";
+import { useRowyContext } from "contexts/RowyContext";
+import useWindowSize from "hooks/useWindowSize";
+import useStyles from "./styles";
+
+export type RowyColumn = Column & {
+ isNew?: boolean;
+ type: FieldType;
+ [key: string]: any;
+};
+
+const rowKeyGetter = (row: any) => row.id;
+const SelectColumn = { ..._SelectColumn, width: 44, maxWidth: 44 };
+
+export default function Table() {
+ const classes = useStyles();
+
+ const {
+ tableState,
+ tableActions,
+ dataGridRef,
+ sideDrawerRef,
+ updateCell,
+ } = useRowyContext();
+ const { userDoc } = useAppContext();
+
+ const userDocHiddenFields =
+ userDoc.state.doc?.tables?.[formatSubTableName(tableState?.tablePath)]
+ ?.hiddenFields ?? [];
+
+ const [columns, setColumns] = useState([]);
+
+ useEffect(() => {
+ if (!tableState?.loadingColumns && tableState?.columns) {
+ const _columns = _orderBy(
+ Object.values(tableState?.columns).filter(
+ (column: any) => !column.hidden && column.key
+ ),
+ "index"
+ )
+ .map((column: any) => ({
+ draggable: true,
+ editable: true,
+ resizable: true,
+ frozen: column.fixed,
+ headerRenderer: ColumnHeader,
+ formatter:
+ getFieldProp(
+ "TableCell",
+ column.config?.renderFieldType ?? column.type
+ ) ??
+ function InDev() {
+ return null;
+ },
+ editor:
+ getFieldProp(
+ "TableEditor",
+ column.config?.renderFieldType ?? column.type
+ ) ??
+ function InDev() {
+ return null;
+ },
+ ...column,
+ width: column.width ? (column.width > 380 ? 380 : column.width) : 150,
+ }))
+ .filter((column) => !userDocHiddenFields.includes(column.key));
+
+ setColumns([
+ // TODO: ENABLE ONCE BULK ACTIONS READY
+ // SelectColumn,
+ ..._columns,
+ {
+ isNew: true,
+ key: "new",
+ name: "Add column",
+ type: FieldType.last,
+ index: _columns.length ?? 0,
+ width: 204,
+ headerRenderer: FinalColumnHeader,
+ headerCellClass: "final-column-header",
+ cellClass: "final-column-cell",
+ formatter: FinalColumn,
+ editable: false,
+ },
+ ]);
+ }
+ }, [
+ tableState?.loadingColumns,
+ tableState?.columns,
+ JSON.stringify(userDocHiddenFields),
+ ]);
+
+ const rows =
+ useMemo(
+ () =>
+ tableState?.rows.map((row) =>
+ columns.reduce(
+ (acc, currColumn) => {
+ if ((currColumn.key as string).includes(".")) {
+ return {
+ ...acc,
+ [currColumn.key]: _get(row, currColumn.key),
+ };
+ } else return acc;
+ },
+ { ...row, id: row.id as string, ref: row.ref }
+ )
+ ),
+ [columns, tableState?.rows]
+ ) ?? [];
+
+ const rowsContainerRef = useRef(null);
+ const [selectedRowsSet, setSelectedRowsSet] = useState>();
+ const [selectedRows, setSelectedRows] = useState([]);
+ // Gets more rows when scrolled down.
+ // https://github.com/adazzle/react-data-grid/blob/ead05032da79d7e2b86e37cdb9af27f2a4d80b90/stories/demos/AllFeatures.tsx#L60
+ const handleScroll = (event: React.UIEvent) => {
+ const target = event.target as HTMLDivElement;
+ const offset = 800;
+ const isAtBottom =
+ target.clientHeight + target.scrollTop >= target.scrollHeight - offset;
+
+ if (!isAtBottom) return;
+
+ // Prevent calling more rows when they’ve already been called
+ if (tableState!.loadingRows) return;
+
+ // Call for 30 more rows. Note we don’t know here if there are no more
+ // rows left in the database. This is done in the useTable hook.
+ tableActions?.row.more(30);
+ };
+
+ const windowSize = useWindowSize();
+ if (!windowSize || !windowSize.height) return <>>;
+
+ if (!tableActions || !tableState) return <>>;
+
+ const rowHeight = tableState.config.rowHeight;
+
+ return (
+ <>
+ {/* }>
+
+ */}
+
+
+
+ {!tableState.loadingColumns ? (
+
+ {
+ const newSelectedArray = newSelectedSet
+ ? [...newSelectedSet]
+ : [];
+ const prevSelectedRowsArray = selectedRowsSet
+ ? [...selectedRowsSet]
+ : [];
+ const addedSelections = _difference(
+ newSelectedArray,
+ prevSelectedRowsArray
+ );
+ const removedSelections = _difference(
+ prevSelectedRowsArray,
+ newSelectedArray
+ );
+ addedSelections.forEach((id) => {
+ const newRow = _find(rows, { id });
+ setSelectedRows([...selectedRows, newRow]);
+ });
+ removedSelections.forEach((rowId) => {
+ setSelectedRows(
+ selectedRows.filter((row) => row.id !== rowId)
+ );
+ });
+ setSelectedRowsSet(newSelectedSet);
+ }}
+ onRowsChange={() => {
+ //console.log('onRowsChange',rows)
+ }}
+ onFill={(e) => {
+ console.log("onFill", e);
+ const { columnKey, sourceRow, targetRows } = e;
+ if (updateCell)
+ targetRows.forEach((row) =>
+ updateCell(row.ref, columnKey, sourceRow[columnKey])
+ );
+ return [];
+ }}
+ onPaste={(e) => {
+ const copiedValue = e.sourceRow[e.sourceColumnKey];
+ if (updateCell) {
+ updateCell(e.targetRow.ref, e.targetColumnKey, copiedValue);
+ }
+ }}
+ onRowClick={(rowIdx, column) => {
+ if (sideDrawerRef?.current) {
+ sideDrawerRef.current.setCell({
+ row: rowIdx,
+ column: column.key as string,
+ });
+ }
+ }}
+ />
+
+ ) : (
+
+ )}
+
+
+
+ {
+ setSelectedRowsSet(new Set());
+ setSelectedRows([]);
+ }}
+ />
+ >
+ );
+}
diff --git a/src/components/Table/styles.ts b/src/components/Table/styles.ts
new file mode 100644
index 000000000..52a1bc590
--- /dev/null
+++ b/src/components/Table/styles.ts
@@ -0,0 +1,115 @@
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { alpha, emphasize, darken, lighten } from "@material-ui/core";
+import { APP_BAR_HEIGHT } from "components/Navigation";
+// import { DRAWER_COLLAPSED_WIDTH } from "components/SideDrawer";
+
+export const useStyles = makeStyles((theme) =>
+ createStyles({
+ tableWrapper: {
+ display: "flex",
+ flexDirection: "column",
+ // width: `calc(100% - ${DRAWER_COLLAPSED_WIDTH}px)`,
+ height: `calc(100vh - ${APP_BAR_HEIGHT}px)`,
+
+ "& > .rdg": { flex: 1 },
+
+ [theme.breakpoints.down("sm")]: { width: "100%" },
+ },
+
+ loadingContainer: {
+ position: "sticky",
+ left: 0,
+ height: 100,
+ },
+
+ "@global": {
+ ".rdg.rdg": {
+ "--color": theme.palette.text.primary,
+ "--border-color": theme.palette.divider,
+ // "--summary-border-color": "#aaa",
+ "--background-color": theme.palette.background.paper,
+ "--header-background-color": theme.palette.background.default,
+ "--row-hover-background-color": emphasize(
+ theme.palette.background.paper,
+ 0.04
+ ),
+ "--row-selected-background-color":
+ theme.palette.mode === "light"
+ ? lighten(theme.palette.primary.main, 0.9)
+ : darken(theme.palette.primary.main, 0.8),
+ "--row-selected-hover-background-color":
+ theme.palette.mode === "light"
+ ? lighten(theme.palette.primary.main, 0.8)
+ : darken(theme.palette.primary.main, 0.7),
+ "--checkbox-color": theme.palette.primary.main,
+ "--checkbox-focus-color": theme.palette.primary.main,
+ "--checkbox-disabled-border-color": "#ccc",
+ "--checkbox-disabled-background-color": "#ddd",
+ "--selection-color": theme.palette.primary.main,
+ "--font-size": "0.75rem",
+ "--cell-padding": theme.spacing(0, 1.5),
+
+ border: "none",
+ backgroundColor: "transparent",
+
+ ...theme.typography.body2,
+ fontSize: "0.8125rem",
+ lineHeight: "inherit !important",
+
+ "& .rdg-cell": {
+ display: "flex",
+ alignItems: "center",
+ padding: "var(--cell-padding)",
+
+ overflow: "visible",
+ contain: "none",
+ },
+
+ "& .rdg-cell-frozen-last": {
+ // boxShadow:
+ // theme.palette.mode === "light"
+ // ? "2px 0 4px 0px rgba(0, 0, 0, .08)"
+ // : "2px 0 4px 0px rgba(0, 0, 0, .67)",
+ boxShadow: theme.shadows[2]
+ .replace(/, 0 (\d+px)/g, ", $1 0")
+ .split("),")
+ .slice(1)
+ .join("),"),
+ },
+
+ "& .rdg-cell-copied": {
+ backgroundColor:
+ theme.palette.mode === "light"
+ ? lighten(theme.palette.primary.main, 0.7)
+ : darken(theme.palette.primary.main, 0.6),
+ },
+ },
+
+ ".rdg-header-row .rdg-cell": {
+ borderTop: "1px solid var(--border-color)",
+ },
+
+ ".rdg-row:hover": { color: theme.palette.text.primary },
+
+ ".row-hover-iconButton": {
+ color: theme.palette.text.disabled,
+ transitionDuration: "0s",
+
+ ".rdg-row:hover &": {
+ color: theme.palette.text.primary,
+ backgroundColor: alpha(
+ theme.palette.text.primary,
+ theme.palette.action.hoverOpacity * 2
+ ),
+ },
+ },
+
+ ".cell-collapse-padding": {
+ margin: theme.spacing(0, -1.5),
+ width: `calc(100% + ${theme.spacing(3)})`,
+ },
+ },
+ })
+);
+
+export default useStyles;
diff --git a/src/components/TableSettings/form.tsx b/src/components/TableSettings/form.tsx
new file mode 100644
index 000000000..4eb709b5d
--- /dev/null
+++ b/src/components/TableSettings/form.tsx
@@ -0,0 +1,201 @@
+import { Field, FieldType } from "@antlerengineering/form-builder";
+import { TableSettingsDialogModes } from "./index";
+
+import { Link, Typography } from "@material-ui/core";
+import OpenInNewIcon from "@material-ui/icons/OpenInNew";
+import { projectId } from "../../firebase";
+import WIKI_LINKS from "constants/wikiLinks";
+
+export const tableSettings = (
+ mode: TableSettingsDialogModes | null,
+ roles: string[] | undefined,
+ sections: string[] | undefined,
+ tables: { label: string; value: any }[] | undefined
+): Field[] =>
+ [
+ {
+ type: FieldType.shortText,
+ name: "name",
+ label: "Table Name",
+ required: true,
+ },
+ {
+ type: FieldType.shortText,
+ name: "collection",
+ label: "Collection Name",
+ required: true,
+ assistiveText: (
+
+ View your Firestore collections
+
+
+ ) as any,
+ },
+ {
+ type: FieldType.singleSelect,
+ name: "tableType",
+ label: "Table Type",
+ labelPlural: "table types",
+ searchable: false,
+ defaultValue: "primaryCollection",
+ options: [
+ {
+ label: "Primary Collection",
+ description: `
+ Connect this table to the single collection
+ matching the collection name entered above`,
+ value: "primaryCollection",
+ },
+ {
+ label: "Collection Group",
+ description: `
+ Connect this table to all collections and subcollections
+ matching the collection name entered above`,
+ value: "collectionGroup",
+ },
+ ],
+ required: true,
+ disabled: mode === TableSettingsDialogModes.update,
+ itemRenderer: (option) => (
+
+ {option.label}
+
+
+ ),
+ assistiveText: (
+
+ Learn more about collection groups
+
+
+ ) as any,
+ },
+ {
+ type: FieldType.singleSelect,
+ name: "section",
+ label: "Section",
+ freeText: true,
+ options: sections,
+ required: true,
+ },
+ {
+ type: FieldType.paragraph,
+ name: "description",
+ label: "Description",
+ },
+ {
+ type: FieldType.multiSelect,
+ name: "roles",
+ label: "Accessed By",
+ options: roles ?? [],
+ required: true,
+ freeText: true,
+ assistiveText: (
+ <>
+ Choose which roles have access to this table. Remember to set the
+ appropriate Firestore Security Rules for this collection.
+
+ Read about role-based security rules
+
+
+ >
+ ) as any,
+ },
+ {
+ type: FieldType.slider,
+ name: "triggerDepth",
+ defaultValue: 1,
+ min: 1,
+ max: 5,
+ label: "Collection Depth",
+ displayCondition: "return values.tableType === 'collectionGroup'",
+ assistiveText: (
+ <>
+ Rowy Cloud Functions that rely on{" "}
+
+ Firestore triggers
+ {" "}
+ on this table require you to manually set the depth of this collection
+ group.
+
+
+ Learn more about this requirement
+
+
+ >
+ ),
+ },
+ mode === TableSettingsDialogModes.create && tables && tables?.length !== 0
+ ? {
+ type: FieldType.singleSelect,
+ name: "schemaSource",
+ label: "Copy column config from existing table",
+ labelPlural: "Tables",
+ options: tables,
+ freeText: false,
+ itemRenderer: (option: { value: string; label: string }) => (
+
+ {option.label}
+ theme.typography.fontFamilyMono,
+ display: "block",
+ }}
+ >
+ {option.value}
+
+
+ ),
+ }
+ : null,
+ ].filter((field) => field !== null) as Field[];
diff --git a/src/components/TableSettings/index.tsx b/src/components/TableSettings/index.tsx
new file mode 100644
index 000000000..98f9b3902
--- /dev/null
+++ b/src/components/TableSettings/index.tsx
@@ -0,0 +1,277 @@
+import { useState, useEffect } from "react";
+import _camelCase from "lodash/camelCase";
+import _find from "lodash/find";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { Button, DialogContentText } from "@material-ui/core";
+
+import Confirmation from "components/Confirmation";
+
+import { FormDialog } from "@antlerengineering/form-builder";
+import { tableSettings } from "./form";
+
+import { useRowyContext } from "contexts/RowyContext";
+import useRouter from "../../hooks/useRouter";
+import { db } from "../../firebase";
+
+export enum TableSettingsDialogModes {
+ create,
+ update,
+}
+export interface ICreateTableDialogProps {
+ mode: TableSettingsDialogModes | null;
+ clearDialog: () => void;
+ data: {
+ name: string;
+ collection: string;
+ tableType: string;
+ section: string;
+ description: string;
+ isCollectionGroup: boolean;
+ roles: string[];
+ } | null;
+}
+
+const FORM_EMPTY_STATE = {
+ name: "",
+ collection: "",
+ section: "",
+ description: "",
+ isCollectionGroup: false,
+ roles: ["ADMIN"],
+};
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ buttonGrid: { padding: theme.spacing(3, 0) },
+ button: { width: 160 },
+
+ formFooter: {
+ marginTop: theme.spacing(4),
+
+ "& button": {
+ paddingLeft: theme.spacing(1.5),
+ display: "flex",
+ },
+ },
+ collectionName: { fontFamily: theme.typography.fontFamilyMono },
+ })
+);
+
+export default function TableSettingsDialog({
+ mode,
+ clearDialog,
+ data,
+}: ICreateTableDialogProps) {
+ const classes = useStyles();
+
+ const { settingsActions, sections, roles, tables } = useRowyContext();
+ const sectionNames = sections ? Object.keys(sections) : [];
+
+ const router = useRouter();
+ const open = mode !== null;
+
+ const [formState, setForm] = useState(FORM_EMPTY_STATE);
+
+ const handleChange = (key: string, value: any) =>
+ setForm({ ...formState, [key]: value });
+
+ useEffect(() => {
+ if (mode === TableSettingsDialogModes.create)
+ handleChange("collection", _camelCase(formState.name));
+ }, [formState.name]);
+
+ const handleClose = () => {
+ setForm(FORM_EMPTY_STATE);
+ clearDialog();
+ };
+
+ useEffect(() => {
+ if (data) setForm(data);
+ }, [data]);
+
+ if (!open) return null;
+
+ const handleSubmit = async (values) => {
+ const data: any = {
+ ...values,
+ isCollectionGroup: values.tableType === "collectionGroup",
+ };
+
+ if (values.schemaSource)
+ data.schemaSource = _find(tables, { collection: values.schemaSource });
+
+ if (mode === TableSettingsDialogModes.update) {
+ await Promise.all([settingsActions?.updateTable(data), handleClose()]);
+ window.location.reload();
+ } else {
+ settingsActions?.createTable(data);
+
+ if (router.location.pathname === "/") {
+ router.history.push(
+ `${values.tableType === "collectionGroup" ? "tableGroup" : "table"}/${
+ values.collection
+ }`
+ );
+ } else {
+ router.history.push(values.collection);
+ }
+ }
+
+ handleClose();
+ };
+
+ const handleResetStructure = async () => {
+ const schemaDocRef = db.doc(`_rowy_/settings/schema/${data!.collection}`);
+ await schemaDocRef.update({ columns: {} });
+ handleClose();
+ };
+
+ const handleDelete = async () => {
+ const tablesDocRef = db.doc(`_rowy_/settings`);
+ const tableData = (await tablesDocRef.get()).data();
+ const updatedTables = tableData?.tables.filter(
+ (table) =>
+ table.collection !== data?.collection ||
+ table.isCollectionGroup !== data?.isCollectionGroup
+ );
+ await tablesDocRef.update({ tables: updatedTables });
+ await tablesDocRef
+ .collection(Boolean(data?.isCollectionGroup) ? "schema" : "groupSchema")
+ .doc(data?.collection)
+ .delete();
+ window.location.reload();
+ handleClose();
+ };
+
+ return (
+ ({ label: table.name, value: table.collection }))
+ )}
+ values={{
+ tableType: data?.isCollectionGroup
+ ? "collectionGroup"
+ : "primaryCollection",
+ ...data,
+ }}
+ onSubmit={handleSubmit}
+ SubmitButtonProps={{
+ children:
+ mode === TableSettingsDialogModes.create ? "Create" : "Update",
+ }}
+ // customActions={
+ //
+ //
+ //
+ // Cancel
+ //
+ //
+ //
+ //
+ // {mode === TableSettingsDialogModes.create ? "Create" : "Update"}
+ //
+ //
+ //
+ // }
+ formFooter={
+ mode === TableSettingsDialogModes.update ? (
+
+
+
+ This will only delete the column structure for this table,
+ so you can set up the columns again.
+
+
+ You will not lose any data in your Firestore collection
+ named “
+
+ {formState.collection}
+
+ ” .
+
+ >
+ ),
+ confirm: "Reset",
+ color: "error",
+ }}
+ functionName="onClick"
+ >
+ }
+ >
+ Reset Table Structure…
+
+
+
+
+
+
+
+ This will only delete the Rowy configuration data.
+
+
+ You will not lose any data in your Firestore collection
+ named “
+
+ {formState.collection}
+
+ ” .
+
+ >
+ ),
+ confirm: "Delete",
+ color: "error",
+ }}
+ functionName="onClick"
+ >
+ }
+ >
+ Delete Table…
+
+
+
+ ) : null
+ }
+ />
+ );
+}
diff --git a/src/components/Thumbnail.tsx b/src/components/Thumbnail.tsx
new file mode 100644
index 000000000..516d635e1
--- /dev/null
+++ b/src/components/Thumbnail.tsx
@@ -0,0 +1,126 @@
+import React, { Suspense } from "react";
+import clsx from "clsx";
+import { useImage } from "react-image";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import Skeleton from "@material-ui/core/Skeleton";
+
+import ErrorBoundary from "./ErrorBoundary";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: ({
+ objectFit,
+ shape,
+ border,
+ }: Pick) => ({
+ objectFit: objectFit as any,
+ borderRadius:
+ shape === "circle"
+ ? "50%"
+ : shape === "square"
+ ? 0
+ : theme.shape.borderRadius,
+
+ display: "block",
+ pointerEvents: "none",
+ userSelect: "none",
+
+ position: "relative",
+
+ "&::after": {
+ content: '""',
+ display: "block",
+ position: "absolute",
+ top: 0,
+ left: 0,
+ width: "100%",
+ height: "100%",
+
+ boxShadow: border ? `0 0 0 1px ${theme.palette.divider} inset` : "none",
+ },
+ }),
+
+ skeleton: ({ shape }: Pick) => ({
+ borderRadius:
+ shape === "circle"
+ ? "50%"
+ : shape === "square"
+ ? 0
+ : theme.shape.borderRadius,
+ display: "block",
+ }),
+ })
+);
+
+export interface IThubmnailProps
+ extends React.DetailedHTMLProps<
+ React.ImgHTMLAttributes,
+ HTMLImageElement
+ > {
+ imageUrl: string;
+ size?: string;
+
+ objectFit?: string;
+ shape?: "roundedRectangle" | "square" | "circle";
+ border?: boolean;
+}
+
+/**
+ * Display a thumbnail generated by compressedThumbnail cloud function,
+ * falling back to original image if it doesn’t load.
+ *
+ * Uses react-image: https://github.com/mbrevda/react-image
+ */
+export function Thubmnail_({
+ imageUrl,
+ size = "200x200",
+
+ objectFit = "cover",
+ shape = "roundedRectangle",
+ border = false,
+
+ ...props
+}: IThubmnailProps) {
+ const classes = useStyles({ objectFit, shape, border });
+
+ // Add size suffix just before file name extension (e.g. .jpg)
+ const thumbnailUrl = imageUrl.replace(
+ /(\.[\w]+\?.*token=[\w-]+$)/,
+ `__${size}$1`
+ );
+
+ const { src } = useImage({
+ srcList: [thumbnailUrl, imageUrl],
+ });
+
+ return (
+
+ );
+}
+
+/**
+ * Wrap thumbnail in an ErrorBoundary and Skeleton for loading
+ */
+export default function Thumbnail(props: IThubmnailProps) {
+ const classes = useStyles({ shape: props.shape });
+
+ return (
+
+
+ }
+ >
+
+
+
+ );
+}
diff --git a/src/components/Wizards/Cell.tsx b/src/components/Wizards/Cell.tsx
new file mode 100644
index 000000000..7557ca6b7
--- /dev/null
+++ b/src/components/Wizards/Cell.tsx
@@ -0,0 +1,104 @@
+import React from "react";
+import { makeStyles, createStyles } from "@material-ui/styles";
+
+import { FieldType } from "constants/fields";
+import { getFieldProp } from "components/fields";
+import EmptyState from "components/EmptyState";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: {
+ width: "100%",
+ height: 43,
+ position: "relative",
+ overflow: "hidden",
+ whiteSpace: "nowrap",
+
+ pointerEvents: "none",
+
+ border: `1px solid ${theme.palette.divider}`,
+ borderTopWidth: 0,
+ backgroundColor: theme.palette.background.paper,
+
+ display: "flex",
+ alignItems: "center",
+ padding: theme.spacing(0, 1.5),
+
+ ...theme.typography.body2,
+ fontSize: "0.75rem",
+ lineHeight: "inherit",
+ color: theme.palette.text.secondary,
+
+ "& .cell-collapse-padding": {
+ margin: theme.spacing(0, -1.5),
+ width: `calc(100% + ${theme.spacing(3)})`,
+ },
+ },
+
+ value: {
+ width: "100%",
+ maxHeight: 43,
+
+ display: "flex",
+ justifyContent: "flex-start",
+ alignItems: "center",
+ },
+ })
+);
+
+export interface ICellProps
+ extends Partial<
+ React.DetailedHTMLProps<
+ React.HTMLAttributes,
+ HTMLDivElement
+ >
+ > {
+ field: string;
+ type: FieldType;
+ value: any;
+ name?: string;
+}
+
+export default function Cell({
+ field,
+ type,
+ value,
+ name,
+ ...props
+}: ICellProps) {
+ const classes = useStyles();
+ const formatter = type ? getFieldProp("TableCell", type) : null;
+
+ return (
+
+
+ {formatter ? (
+ React.createElement(formatter, {
+ value,
+ rowIdx: 0,
+ column: {
+ type,
+ key: field,
+ name,
+ config: { options: [] },
+ editable: false,
+ } as any,
+ row: { [field]: value },
+ isRowSelected: false,
+ onRowSelectionChange: () => {},
+ isSummaryRow: false,
+ } as any)
+ ) : typeof value === "string" ||
+ typeof value === "number" ||
+ value === undefined ||
+ value === null ? (
+ value
+ ) : typeof value === "boolean" ? (
+ value.toString()
+ ) : (
+
+ )}
+
+
+ );
+}
diff --git a/src/components/Wizards/Column.tsx b/src/components/Wizards/Column.tsx
new file mode 100644
index 000000000..899d1706f
--- /dev/null
+++ b/src/components/Wizards/Column.tsx
@@ -0,0 +1,112 @@
+import clsx from "clsx";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { Grid, GridProps, Typography } from "@material-ui/core";
+import { alpha } from "@material-ui/core/styles";
+
+import { FieldType } from "constants/fields";
+import { getFieldProp } from "components/fields";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: {
+ width: "100%",
+ height: 44,
+ border: `1px solid ${theme.palette.divider}`,
+ backgroundColor: theme.palette.background.default,
+
+ padding: theme.spacing(0, 1, 0, 1.5),
+
+ color: theme.palette.text.secondary,
+ "&:hover": { color: theme.palette.text.primary },
+
+ "& svg": { display: "block" },
+ },
+
+ active: {
+ backgroundColor: alpha(
+ theme.palette.primary.main,
+ theme.palette.action.selectedOpacity
+ ),
+ color:
+ theme.palette.mode === "dark"
+ ? theme.palette.text.primary
+ : theme.palette.primary.dark,
+ borderColor: alpha(
+ theme.palette.primary.main,
+ theme.palette.action.disabledOpacity
+ ),
+
+ "&:hover": {
+ color:
+ theme.palette.mode === "dark"
+ ? theme.palette.text.primary
+ : theme.palette.primary.dark,
+ },
+ },
+
+ columnNameContainer: {
+ flexShrink: 1,
+ overflow: "hidden",
+ },
+ columnName: {
+ lineHeight: "44px",
+ display: "block",
+
+ userSelect: "none",
+
+ marginLeft: theme.spacing(0.5),
+ },
+
+ secondaryItem: { marginLeft: theme.spacing(1) },
+ })
+);
+
+export interface IColumnProps extends Partial {
+ label: string;
+ type?: FieldType;
+ secondaryItem?: React.ReactNode;
+
+ active?: boolean;
+}
+
+export default function Column({
+ label,
+ type,
+ secondaryItem,
+
+ active,
+ ...props
+}: IColumnProps) {
+ const classes = useStyles();
+
+ return (
+
+ {type && {getFieldProp("icon", type)} }
+
+
+
+ {label}
+
+
+
+ {secondaryItem && (
+
+ {secondaryItem}
+
+ )}
+
+ );
+}
diff --git a/src/components/Wizards/FadeList.tsx b/src/components/Wizards/FadeList.tsx
new file mode 100644
index 000000000..d95d11498
--- /dev/null
+++ b/src/components/Wizards/FadeList.tsx
@@ -0,0 +1,58 @@
+import React from "react";
+import clsx from "clsx";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ listWrapper: {
+ position: "relative",
+
+ "&::after": {
+ content: '""',
+ display: "block",
+ pointerEvents: "none",
+
+ position: "absolute",
+ bottom: 0,
+ left: 0,
+ right: 0,
+
+ height: theme.spacing(3),
+ backgroundImage: `linear-gradient(to top, ${theme.palette.background.paper}, transparent)`,
+ },
+ },
+ list: {
+ listStyleType: "none",
+ margin: 0,
+ padding: theme.spacing(1.5, 0, 3),
+
+ height: 400,
+ overflowY: "overlay" as any,
+
+ "& li": { margin: theme.spacing(0.5, 0) },
+ },
+ })
+);
+
+export interface IFadeListProps {
+ children?: React.ReactNode | React.ElementType[];
+ classes?: Partial>;
+}
+
+export const FadeList = React.forwardRef(
+ function FadeList_({ children, classes: classesProp }, ref) {
+ const classes = useStyles();
+
+ return (
+
+ );
+ }
+);
+
+export default FadeList;
diff --git a/src/components/Wizards/ImportCsvWizard/Step1Columns.tsx b/src/components/Wizards/ImportCsvWizard/Step1Columns.tsx
new file mode 100644
index 000000000..456a5ab45
--- /dev/null
+++ b/src/components/Wizards/ImportCsvWizard/Step1Columns.tsx
@@ -0,0 +1,280 @@
+import { useState } from "react";
+import MultiSelect from "@antlerengineering/multiselect";
+import _find from "lodash/find";
+import _findIndex from "lodash/findIndex";
+import _camel from "lodash/camelCase";
+import _sortBy from "lodash/sortBy";
+import clsx from "clsx";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import {
+ Grid,
+ Typography,
+ Divider,
+ FormControlLabel,
+ Checkbox,
+ Chip,
+} from "@material-ui/core";
+import ArrowIcon from "@material-ui/icons/ArrowForward";
+
+import { IStepProps } from ".";
+import FadeList from "../FadeList";
+import Column from "../Column";
+
+import { useRowyContext } from "contexts/RowyContext";
+import { FieldType } from "constants/fields";
+import { suggestType } from "../ImportWizard/utils";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ csvListItem: { display: "flex" },
+ csvColumn: {},
+
+ formControlLabel: {
+ marginRight: 0,
+ flex: 1,
+ },
+ columnLabel: { flex: 1 },
+
+ arrowGridItem: {
+ width: theme.spacing(7),
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ },
+ activeArrow: { color: theme.palette.secondary.main },
+
+ multiSelectInput: {
+ backgroundColor: theme.palette.background.default,
+ border: `1px solid ${theme.palette.divider}`,
+ borderRadius: 0,
+
+ ...theme.typography.subtitle2,
+ color: theme.palette.text.secondary,
+ transition: theme.transitions.create("color", {
+ duration: theme.transitions.duration.short,
+ }),
+ "&:hover": {
+ backgroundColor: theme.palette.background.default,
+ color: theme.palette.text.primary,
+ },
+
+ "&::before": { content: "none" },
+ "&::after": { pointerEvents: "none" },
+ },
+ noneSelected: { color: theme.palette.text.disabled },
+ multiSelectInputLabel: {
+ padding: theme.spacing(0, 2),
+ height: 44 - 2,
+
+ display: "flex",
+ alignItems: "center",
+ },
+ newColumnChip: {
+ marginLeft: theme.spacing(1),
+ backgroundColor: theme.palette.action.focus,
+ ...theme.typography.overline,
+ pointerEvents: "none",
+ },
+ })
+);
+
+export default function Step1Columns({
+ csvData,
+ config,
+ updateConfig,
+ setConfig,
+ isXs,
+}: IStepProps) {
+ const classes = useStyles();
+
+ const { tableState } = useRowyContext();
+ const tableColumns = _sortBy(Object.values(tableState?.columns ?? {}), [
+ "index",
+ ]).map((column) => ({ label: column.name, value: column.key }));
+
+ const [selectedFields, setSelectedFields] = useState(
+ config.pairs.map((pair) => pair.csvKey)
+ );
+
+ const handleSelect = (field: string) => (e) => {
+ const checked = e.target.checked;
+
+ if (checked) {
+ setSelectedFields((x) => [...x, field]);
+ } else {
+ const newValue = [...selectedFields];
+ newValue.splice(newValue.indexOf(field), 1);
+ setSelectedFields(newValue);
+
+ // Check if this pair was already pushed to main config
+ const configPair = _find(config.pairs, { csvKey: field });
+ const configIndex = _findIndex(config.pairs, { csvKey: field });
+
+ // Delete matching newColumn if it was created
+ if (configPair) {
+ const newColumnIndex = _findIndex(config.newColumns, {
+ key: configPair.columnKey,
+ });
+ if (newColumnIndex > -1) {
+ const newColumns = [...config.newColumns];
+ newColumns.splice(newColumnIndex, 1);
+ setConfig((config) => ({ ...config, newColumns }));
+ }
+ }
+
+ // Delete pair from main config
+ if (configIndex > -1) {
+ const newConfig = [...config.pairs];
+ newConfig.splice(configIndex, 1);
+ setConfig((config) => ({ ...config, pairs: newConfig }));
+ }
+ }
+ };
+
+ const handleChange = (csvKey: string) => (value: string) => {
+ const columnKey = !!tableState?.columns[value] ? value : _camel(value);
+
+ // Check if this pair already exists in config
+ const configIndex = _findIndex(config.pairs, { csvKey });
+ if (configIndex > -1) {
+ const pairs = [...config.pairs];
+ pairs[configIndex].columnKey = columnKey;
+ setConfig((config) => ({ ...config, pairs }));
+ } else {
+ updateConfig({
+ pairs: [{ csvKey, columnKey }],
+ });
+ }
+
+ if (!tableState?.columns[value]) {
+ updateConfig({
+ newColumns: [
+ {
+ name: value,
+ fieldName: columnKey,
+ key: columnKey,
+ type: suggestType(csvData.rows, csvKey) || FieldType.shortText,
+ index: -1,
+ config: {},
+ },
+ ],
+ });
+ }
+ };
+
+ return (
+
+
+ {!isXs && (
+
+
+ Select Columns ({config.pairs.length} of {csvData.columns.length})
+
+
+ )}
+
+
+ Rowy Columns
+
+
+
+
+
+
+
+ {csvData.columns.map((field) => {
+ const selected = selectedFields.indexOf(field) > -1;
+ const columnKey =
+ _find(config.pairs, { csvKey: field })?.columnKey ?? null;
+ const matchingColumn = columnKey
+ ? tableState?.columns[columnKey] ??
+ _find(config.newColumns, { key: columnKey }) ??
+ null
+ : null;
+ const isNewColumn = !!_find(config.newColumns, { key: columnKey });
+
+ return (
+
+
+
+ }
+ label={ }
+ classes={{
+ root: classes.formControlLabel,
+ label: classes.columnLabel,
+ }}
+ />
+
+
+
+
+
+
+
+ {selected && (
+ {
+ if (!columnKey) return "Select or add column";
+ else
+ return (
+ <>
+ {matchingColumn?.name}
+ {isNewColumn && (
+
+ )}
+ >
+ );
+ },
+ },
+ InputProps: {
+ classes: {
+ root: clsx(
+ classes.multiSelectInput,
+ !columnKey && classes.noneSelected
+ ),
+ inputHiddenLabel: classes.multiSelectInputLabel,
+ },
+ },
+ }}
+ clearable={false}
+ displayEmpty
+ labelPlural="columns"
+ freeText
+ AddButtonProps={{ children: "Add New Column" }}
+ AddDialogProps={{
+ title: "Add New Column",
+ textFieldLabel: "Column Name",
+ }}
+ />
+ )}
+
+
+ );
+ })}
+
+
+ );
+}
diff --git a/src/components/Wizards/ImportCsvWizard/Step2NewColumns.tsx b/src/components/Wizards/ImportCsvWizard/Step2NewColumns.tsx
new file mode 100644
index 000000000..9a1e6f305
--- /dev/null
+++ b/src/components/Wizards/ImportCsvWizard/Step2NewColumns.tsx
@@ -0,0 +1,176 @@
+import { useState } from "react";
+import _find from "lodash/find";
+import { parseJSON } from "date-fns";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { Grid, Typography, Divider, ButtonBase } from "@material-ui/core";
+import ChevronRightIcon from "@material-ui/icons/ChevronRight";
+
+import { IStepProps } from ".";
+import FadeList from "../FadeList";
+import Column from "../Column";
+import Cell from "../Cell";
+import FieldsDropdown from "components/Table/ColumnMenu/FieldsDropdown";
+
+import { FieldType } from "constants/fields";
+import { SELECTABLE_TYPES } from "../ImportWizard/utils";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ typeSelectRow: { marginBottom: theme.spacing(3) },
+
+ buttonBase: {
+ width: "100%",
+ textAlign: "left",
+ },
+
+ typeHeading: { margin: theme.spacing(5, 0, 1) },
+
+ previewDivider: { marginBottom: theme.spacing(2) },
+ previewList: { paddingTop: 0 },
+ previewSpacer: { width: theme.spacing(3) },
+ cellContainer: { overflow: "hidden" },
+ })
+);
+
+export default function Step2NewColumns({
+ csvData,
+ config,
+ setConfig,
+ isXs,
+}: IStepProps) {
+ const classes = useStyles();
+
+ const [fieldToEdit, setFieldToEdit] = useState(0);
+
+ const handleChange = (e) => {
+ const newColumns = [...config.newColumns];
+ newColumns[fieldToEdit].type = e.target.value;
+
+ setConfig((config) => ({ ...config, newColumns }));
+ };
+
+ const currentPair = _find(config.pairs, {
+ columnKey: config.newColumns[fieldToEdit]?.key,
+ });
+ const rowData = csvData.rows.map((row) => row[currentPair?.csvKey ?? ""]);
+
+ return (
+ <>
+
+
+
+
+ New Rowy Columns
+
+
+
+
+ {config.newColumns.map(({ key, name, type }, i) => (
+
+ setFieldToEdit(i)}
+ aria-label={`Edit column ${key}`}
+ focusRipple
+ >
+ }
+ />
+
+
+ ))}
+
+
+
+
+ Column Type: {config.newColumns[fieldToEdit].name}
+
+
+
+
+
+
+
+
+
+ {!isXs && (
+
+
+ Raw Data
+
+
+ )}
+
+
+ Column Preview
+
+
+
+
+
+
+
+ {!isXs && (
+
+
+
+ )}
+
+
+
+
+
+
+ {rowData.slice(0, 20).map((cell, i) => (
+
+ {!isXs && (
+
+ |
+
+ )}
+
+ {!isXs && }
+
+
+ |
+
+
+ ))}
+
+
+ >
+ );
+}
diff --git a/src/components/Wizards/ImportCsvWizard/Step3Preview.tsx b/src/components/Wizards/ImportCsvWizard/Step3Preview.tsx
new file mode 100644
index 000000000..dc29186fd
--- /dev/null
+++ b/src/components/Wizards/ImportCsvWizard/Step3Preview.tsx
@@ -0,0 +1,122 @@
+import { ScrollSync, ScrollSyncPane } from "react-scroll-sync";
+import _find from "lodash/find";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { Grid } from "@material-ui/core";
+
+import { IStepProps } from ".";
+import Column from "../Column";
+import Cell from "../Cell";
+
+import { useRowyContext } from "contexts/RowyContext";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: {
+ position: "relative",
+
+ "&::after": {
+ content: '""',
+ display: "block",
+ pointerEvents: "none",
+
+ position: "absolute",
+ bottom: 0,
+ left: 0,
+ right: 0,
+
+ height: theme.spacing(3),
+ backgroundImage: `linear-gradient(to top, ${theme.palette.background.paper}, transparent)`,
+ },
+
+ "&::before": {
+ content: '""',
+ display: "block",
+ pointerEvents: "none",
+ zIndex: 1,
+
+ position: "absolute",
+ top: 0,
+ bottom: 0,
+ right: 0,
+
+ width: theme.spacing(3),
+ backgroundImage: `linear-gradient(to left, ${theme.palette.background.paper}, transparent)`,
+ },
+ },
+
+ spacer: {
+ width: theme.spacing(3),
+ height: theme.spacing(3),
+ flexShrink: 0,
+ },
+
+ header: { overflowX: "hidden" },
+ data: {
+ overflow: "scroll",
+ height: 300,
+ },
+
+ column: {
+ width: 200,
+ flexShrink: 0,
+ marginLeft: -1,
+
+ "&:first-of-type": { marginLeft: 0 },
+ },
+ })
+);
+
+export default function Step4Preview({ csvData, config }: IStepProps) {
+ const classes = useStyles();
+ const { tableState } = useRowyContext();
+
+ if (!tableState) return null;
+
+ const columns = config.pairs.map(({ csvKey, columnKey }) => ({
+ csvKey,
+ columnKey,
+ ...(tableState!.columns[columnKey] ??
+ _find(config.newColumns, { key: columnKey }) ??
+ {}),
+ }));
+
+ return (
+
+
+
+
+
+ {columns.map(({ key, name, type }) => (
+
+
+
+ ))}
+
+
+
+
+
+
+ {columns.map(({ csvKey, name, columnKey, type }) => (
+
+ {csvData.rows.map((row, i) => (
+ |
+ ))}
+
+
+ ))}
+
+
+
+
+
+
+ );
+}
diff --git a/src/components/Wizards/ImportCsvWizard/index.tsx b/src/components/Wizards/ImportCsvWizard/index.tsx
new file mode 100644
index 000000000..267104fa7
--- /dev/null
+++ b/src/components/Wizards/ImportCsvWizard/index.tsx
@@ -0,0 +1,179 @@
+import React, { useState, useMemo } from "react";
+import _mergeWith from "lodash/mergeWith";
+import _find from "lodash/find";
+
+import { useTheme, useMediaQuery, Typography, Link } from "@material-ui/core";
+import Alert from "@material-ui/core/Alert";
+import AlertTitle from "@material-ui/core/AlertTitle";
+
+import WizardDialog from "../WizardDialog";
+import Step1Columns from "./Step1Columns";
+import Step2NewColumns from "./Step2NewColumns";
+import Step3Preview from "./Step3Preview";
+
+import { ColumnConfig } from "hooks/useRowy/useTableConfig";
+import { useRowyContext } from "contexts/RowyContext";
+import { useSnackContext } from "contexts/SnackContext";
+import { getFieldProp } from "components/fields";
+
+export type CsvConfig = {
+ pairs: { csvKey: string; columnKey: string }[];
+ newColumns: ColumnConfig[];
+};
+
+export interface IStepProps {
+ csvData: NonNullable;
+ config: CsvConfig;
+ setConfig: React.Dispatch>;
+ updateConfig: (value: Partial) => void;
+ isXs: boolean;
+}
+
+export interface IImportCsvWizardProps {
+ handleClose: () => void;
+ csvData: {
+ columns: string[];
+ rows: Record[];
+ } | null;
+}
+
+export default function ImportCsvWizard({
+ handleClose,
+ csvData,
+}: IImportCsvWizardProps) {
+ const theme = useTheme();
+ const isXs = useMediaQuery(theme.breakpoints.down("sm"));
+
+ const [open, setOpen] = useState(true);
+
+ const { tableState, tableActions } = useRowyContext();
+ const { open: openSnackbar } = useSnackContext();
+
+ const [config, setConfig] = useState({
+ pairs: [],
+ newColumns: [],
+ });
+ const updateConfig: IStepProps["updateConfig"] = (value) => {
+ setConfig((prev) => ({
+ ..._mergeWith(prev, value, (objValue, srcValue) =>
+ Array.isArray(objValue) ? objValue.concat(srcValue) : undefined
+ ),
+ }));
+ };
+
+ const parsedRows: any[] = useMemo(() => {
+ if (!tableState || !tableActions || !csvData) return [];
+ return csvData.rows.map((row) =>
+ config.pairs.reduce((a, pair) => {
+ const matchingColumn =
+ tableState.columns[pair.columnKey] ??
+ _find(config.newColumns, { key: pair.columnKey });
+ const csvFieldParser = getFieldProp(
+ "csvImportParser",
+ matchingColumn.type
+ );
+ const value = csvFieldParser
+ ? csvFieldParser(row[pair.csvKey], matchingColumn.config)
+ : row[pair.csvKey];
+ return { ...a, [pair.columnKey]: value };
+ }, {})
+ );
+ }, [csvData, tableState, tableActions, config]);
+
+ const handleFinish = () => {
+ if (!tableState || !tableActions || !parsedRows) return;
+ openSnackbar({ message: "Importing data…" });
+ // Add all new rows — synchronous
+ parsedRows?.forEach((newRow) => tableActions.row.add(newRow));
+
+ // Add any new columns to the end
+ for (const col of config.newColumns) {
+ tableActions.column.add(col.name, col.type, col);
+ }
+ // Close wizard
+ setOpen(false);
+ setTimeout(handleClose, 300);
+ };
+
+ if (!csvData) return null;
+
+ return (
+ {
+ setOpen(false);
+ setTimeout(handleClose, 300);
+ }}
+ title="Import CSV"
+ steps={
+ [
+ {
+ title: "Choose Columns",
+ description: (
+ <>
+
+ Select or add the columns to be imported to your table.
+
+
+ Importing dates?
+ Make sure your dates are in UTC time and{" "}
+
+ a supported format
+
+ . If they’re not, you will need to re-import your CSV data.
+
+ >
+ ),
+ content: (
+
+ ),
+ disableNext: config.pairs.length === 0,
+ },
+ config.newColumns.length > 0 && {
+ title: "Set Column Types",
+ description:
+ "Set the type of each column to display your data correctly. Some column types have been suggested based off your data.",
+ content: (
+
+ ),
+ disableNext: config.newColumns.reduce(
+ (a, c) => a || (c.type as any) === "",
+ false
+ ),
+ },
+ {
+ title: "Preview",
+ description:
+ "Preview your data with your configured columns. You can change column types by clicking “Edit Type” from the column menu at any time.",
+ content: (
+
+ ),
+ },
+ ].filter((x) => x) as any
+ }
+ onFinish={handleFinish}
+ />
+ );
+}
diff --git a/src/components/Wizards/ImportWizard/Step1Columns.tsx b/src/components/Wizards/ImportWizard/Step1Columns.tsx
new file mode 100644
index 000000000..9229e8d60
--- /dev/null
+++ b/src/components/Wizards/ImportWizard/Step1Columns.tsx
@@ -0,0 +1,209 @@
+import { useMemo, useState, useEffect } from "react";
+import {
+ DragDropContext,
+ DropResult,
+ Droppable,
+ Draggable,
+} from "react-beautiful-dnd";
+import _sortBy from "lodash/sortBy";
+import _startCase from "lodash/startCase";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import {
+ Grid,
+ Typography,
+ Divider,
+ FormControlLabel,
+ Checkbox,
+} from "@material-ui/core";
+import DragHandleIcon from "@material-ui/icons/DragHandle";
+
+import { IStepProps } from ".";
+import FadeList from "../FadeList";
+import Column from "../Column";
+import EmptyState from "components/EmptyState";
+import AddColumnIcon from "assets/icons/AddColumn";
+
+import { useRowyContext } from "contexts/RowyContext";
+import { FieldType } from "constants/fields";
+import { suggestType } from "./utils";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ spacer: { height: theme.spacing(1) },
+ formControlLabel: { marginRight: 0 },
+ columnLabel: { flex: 1 },
+ })
+);
+
+export default function Step1Columns({ config, setConfig }: IStepProps) {
+ const classes = useStyles();
+
+ // Get a list of fields from first 50 documents
+ const { tableState } = useRowyContext();
+ const allFields = useMemo(() => {
+ const sample = tableState!.rows.slice(0, 50);
+ const fields_ = new Set();
+ sample.forEach((doc) =>
+ Object.keys(doc).forEach((key) => {
+ if (key !== "ref") fields_.add(key);
+ })
+ );
+ return Array.from(fields_).sort();
+ }, [tableState?.rows]);
+
+ // Store selected fields
+ const [selectedFields, setSelectedFields] = useState(
+ _sortBy(Object.keys(config), "index")
+ );
+
+ const handleSelect = (field: string) => (e) => {
+ const checked = e.target.checked;
+
+ if (checked) {
+ setSelectedFields([...selectedFields, field]);
+ } else {
+ const newSelection = [...selectedFields];
+ newSelection.splice(newSelection.indexOf(field), 1);
+ setSelectedFields(newSelection);
+ }
+ };
+
+ const handleSelectAll = () => {
+ if (selectedFields.length !== allFields.length)
+ setSelectedFields(allFields);
+ else setSelectedFields([]);
+ };
+
+ const handleDragEnd = (result: DropResult) => {
+ const newOrder = [...selectedFields];
+ const [removed] = newOrder.splice(result.source.index, 1);
+ newOrder.splice(result.destination!.index, 0, removed);
+ setSelectedFields(newOrder);
+ };
+
+ useEffect(() => {
+ setConfig(
+ selectedFields.reduce(
+ (a, c, i) => ({
+ ...a,
+ [c]: {
+ fieldName: c,
+ key: c,
+ name: config[c]?.name || _startCase(c),
+ type:
+ config[c]?.type ||
+ suggestType(tableState!.rows, c) ||
+ FieldType.shortText,
+ index: i,
+ config: {},
+ },
+ }),
+ {}
+ )
+ );
+ }, [selectedFields]);
+
+ return (
+
+
+
+ Select Columns ({selectedFields.length} of {allFields.length})
+
+
+
+
+
+
+ }
+ label={
+
+ Select all
+
+ }
+ classes={{
+ root: classes.formControlLabel,
+ label: classes.columnLabel,
+ }}
+ />
+
+
+
+ {allFields.map((field) => (
+
+ -1}
+ aria-label={`Select column ${field}`}
+ onChange={handleSelect(field)}
+ color="default"
+ />
+ }
+ label={ }
+ classes={{
+ root: classes.formControlLabel,
+ label: classes.columnLabel,
+ }}
+ />
+
+ ))}
+
+
+
+
+ Sort Rowy Columns
+
+
+
+ {selectedFields.length === 0 ? (
+
+
+
+ ) : (
+
+
+
+ {(provided) => (
+
+ {selectedFields.map((field, i) => (
+
+
+ {(provided, snapshot) => (
+
+ }
+ />
+
+ )}
+
+
+ ))}
+ {provided.placeholder}
+
+ )}
+
+
+
+ )}
+
+
+ );
+}
diff --git a/src/components/Wizards/ImportWizard/Step2Rename.tsx b/src/components/Wizards/ImportWizard/Step2Rename.tsx
new file mode 100644
index 000000000..bf6cfba4b
--- /dev/null
+++ b/src/components/Wizards/ImportWizard/Step2Rename.tsx
@@ -0,0 +1,141 @@
+import { useState } from "react";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import {
+ Grid,
+ Typography,
+ Divider,
+ IconButton,
+ ButtonBase,
+ TextField,
+ InputAdornment,
+} from "@material-ui/core";
+import EditIcon from "@material-ui/icons/Edit";
+import DoneIcon from "@material-ui/icons/Done";
+
+import { IStepProps } from ".";
+import FadeList from "../FadeList";
+import Column from "../Column";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ spacer: { width: theme.spacing(3) },
+
+ buttonBase: {
+ width: "100%",
+ textAlign: "left",
+ },
+
+ doneButton: { padding: theme.spacing(1) },
+
+ textField: { margin: 0 },
+ inputBaseRoot: {
+ paddingRight: 1,
+ borderRadius: 0,
+ boxShadow: `0 0 0 1px inset ${theme.palette.divider}`,
+ backgroundColor: theme.palette.background.default + " !important",
+
+ ...theme.typography.subtitle2,
+ },
+ inputHiddenLabel: {
+ paddingTop: theme.spacing(14 / 8) + 1,
+ paddingBottom: theme.spacing(14 / 8),
+ paddingLeft: theme.spacing(2) + 1,
+ },
+ })
+);
+
+export default function Step2Rename({
+ config,
+ updateConfig,
+ isXs,
+}: IStepProps) {
+ const classes = useStyles();
+
+ const [fieldToRename, setFieldToRename] = useState("");
+ const [renameTextField, setRenameTextField] = useState("");
+ const handleRename = () => {
+ updateConfig({ [fieldToRename]: { name: renameTextField } });
+ setFieldToRename("");
+ setRenameTextField("");
+ };
+
+ return (
+
+
+ {!isXs && (
+
+
+ Field Names
+
+
+ )}
+
+
+ Set Column Names
+
+
+
+
+
+
+
+ {Object.entries(config).map(([field, { name }]) => (
+
+ {!isXs && (
+
+
+
+ )}
+ {!isXs && }
+
+ {fieldToRename === field ? (
+ setRenameTextField(e.target.value)}
+ onKeyDown={(e) => {
+ if (e.key === "Enter") handleRename();
+ }}
+ InputProps={{
+ endAdornment: (
+
+
+
+
+
+ ),
+ classes: {
+ root: classes.inputBaseRoot,
+ inputHiddenLabel: classes.inputHiddenLabel,
+ },
+ }}
+ hiddenLabel
+ fullWidth
+ autoFocus
+ classes={{ root: classes.textField }}
+ />
+ ) : (
+ {
+ setFieldToRename(field);
+ setRenameTextField(name);
+ }}
+ aria-label={`Rename column ${field}`}
+ focusRipple
+ >
+ } />
+
+ )}
+
+
+ ))}
+
+
+ );
+}
diff --git a/src/components/Wizards/ImportWizard/Step3Types.tsx b/src/components/Wizards/ImportWizard/Step3Types.tsx
new file mode 100644
index 000000000..db64cbb38
--- /dev/null
+++ b/src/components/Wizards/ImportWizard/Step3Types.tsx
@@ -0,0 +1,156 @@
+import { useState } from "react";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { Grid, Typography, Divider, ButtonBase } from "@material-ui/core";
+import ChevronRightIcon from "@material-ui/icons/ChevronRight";
+
+import { IStepProps } from ".";
+import FadeList from "../FadeList";
+import Column from "../Column";
+import Cell from "../Cell";
+import FieldsDropdown from "components/Table/ColumnMenu/FieldsDropdown";
+
+import { useRowyContext } from "contexts/RowyContext";
+import { FieldType } from "constants/fields";
+import { SELECTABLE_TYPES } from "./utils";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ typeSelectRow: { marginBottom: theme.spacing(3) },
+
+ buttonBase: {
+ width: "100%",
+ textAlign: "left",
+ },
+
+ typeHeading: { margin: theme.spacing(5, 0, 1) },
+
+ previewDivider: { marginBottom: theme.spacing(2) },
+ previewList: { paddingTop: 0 },
+ previewSpacer: { width: theme.spacing(3) },
+ cellContainer: { overflow: "hidden" },
+ })
+);
+
+export default function Step3Types({ config, updateConfig, isXs }: IStepProps) {
+ const classes = useStyles();
+
+ const [fieldToEdit, setFieldToEdit] = useState(Object.keys(config)[0]);
+
+ const handleChange = (e) =>
+ updateConfig({ [fieldToEdit]: { type: e.target.value } });
+
+ const { tableState } = useRowyContext();
+
+ return (
+
+
+
+
+ Rowy Columns
+
+
+
+
+ {Object.entries(config).map(([field, { name, type }]) => (
+
+ setFieldToEdit(field)}
+ aria-label={`Edit column ${field}`}
+ focusRipple
+ >
+
+ }
+ />
+
+
+ ))}
+
+
+
+
+ Column Type: {config[fieldToEdit].name}
+
+
+
+
+
+
+
+ {!isXs && (
+
+
+ Raw Data
+
+
+ )}
+
+
+ Column Preview
+
+
+
+
+
+
+
+ {!isXs && (
+
+
+
+ )}
+
+
+
+
+
+
+ {tableState!.rows!.slice(0, 20).map((row) => (
+
+ {!isXs && (
+
+ |
+
+ )}
+
+ {!isXs && }
+
+
+ |
+
+
+ ))}
+
+
+ );
+}
diff --git a/src/components/Wizards/ImportWizard/Step4Preview.tsx b/src/components/Wizards/ImportWizard/Step4Preview.tsx
new file mode 100644
index 000000000..e21e8af06
--- /dev/null
+++ b/src/components/Wizards/ImportWizard/Step4Preview.tsx
@@ -0,0 +1,111 @@
+import { ScrollSync, ScrollSyncPane } from "react-scroll-sync";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { Grid } from "@material-ui/core";
+
+import { IStepProps } from ".";
+import Column from "../Column";
+import Cell from "../Cell";
+
+import { useRowyContext } from "contexts/RowyContext";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: {
+ position: "relative",
+
+ "&::after": {
+ content: '""',
+ display: "block",
+ pointerEvents: "none",
+
+ position: "absolute",
+ bottom: 0,
+ left: 0,
+ right: 0,
+
+ height: theme.spacing(3),
+ backgroundImage: `linear-gradient(to top, ${theme.palette.background.paper}, transparent)`,
+ },
+
+ "&::before": {
+ content: '""',
+ display: "block",
+ pointerEvents: "none",
+ zIndex: 1,
+
+ position: "absolute",
+ top: 0,
+ bottom: 0,
+ right: 0,
+
+ width: theme.spacing(3),
+ backgroundImage: `linear-gradient(to left, ${theme.palette.background.paper}, transparent)`,
+ },
+ },
+
+ spacer: {
+ width: theme.spacing(3),
+ height: theme.spacing(3),
+ flexShrink: 0,
+ },
+
+ header: { overflowX: "hidden" },
+ data: {
+ overflow: "scroll",
+ height: 300,
+ },
+
+ column: {
+ width: 200,
+ flexShrink: 0,
+ marginLeft: -1,
+
+ "&:first-of-type": { marginLeft: 0 },
+ },
+ })
+);
+
+export default function Step4Preview({ config }: IStepProps) {
+ const classes = useStyles();
+ const { tableState } = useRowyContext();
+
+ return (
+
+
+
+
+
+ {Object.entries(config).map(([field, { name, type }]) => (
+
+
+
+ ))}
+
+
+
+
+
+
+ {Object.entries(config).map(([field, { name, type }]) => (
+
+ {tableState!.rows!.slice(0, 20).map((row) => (
+ |
+ ))}
+
+
+ ))}
+
+
+
+
+
+
+ );
+}
diff --git a/src/components/Wizards/ImportWizard/index.tsx b/src/components/Wizards/ImportWizard/index.tsx
new file mode 100644
index 000000000..21271f634
--- /dev/null
+++ b/src/components/Wizards/ImportWizard/index.tsx
@@ -0,0 +1,133 @@
+import React, { useState, useEffect } from "react";
+import _merge from "lodash/merge";
+
+import { useTheme, useMediaQuery, Typography } from "@material-ui/core";
+
+import WizardDialog from "../WizardDialog";
+import Step1Columns from "./Step1Columns";
+import Step2Rename from "./Step2Rename";
+import Step3Types from "./Step3Types";
+import Step4Preview from "./Step4Preview";
+
+import { ColumnConfig } from "hooks/useRowy/useTableConfig";
+import { useRowyContext } from "contexts/RowyContext";
+
+export type TableColumnsConfig = { [key: string]: ColumnConfig };
+
+export type ImportWizardRef = {
+ open: boolean;
+ setOpen: React.Dispatch>;
+};
+
+export interface IStepProps {
+ config: TableColumnsConfig;
+ setConfig: React.Dispatch>;
+ updateConfig: (value: Partial) => void;
+ isXs: boolean;
+}
+
+export default function ImportWizard() {
+ const theme = useTheme();
+ const isXs = useMediaQuery(theme.breakpoints.down("sm"));
+
+ const { tableState, tableActions, importWizardRef } = useRowyContext();
+
+ const [open, setOpen] = useState(false);
+ if (importWizardRef) importWizardRef.current = { open, setOpen };
+
+ const [config, setConfig] = useState({});
+ const updateConfig: IStepProps["updateConfig"] = (value) => {
+ setConfig((prev) => ({ ..._merge(prev, value) }));
+ };
+
+ useEffect(() => {
+ if (!tableState || !open) return;
+
+ if (Array.isArray(tableState.filters) && tableState.filters?.length > 0)
+ tableActions!.table.filter([]);
+
+ if (Array.isArray(tableState.orderBy) && tableState.orderBy?.length > 0)
+ tableActions!.table.orderBy([]);
+ }, [open, tableState]);
+
+ if (tableState?.rows.length === 0) return null;
+
+ const handleFinish = () => {
+ tableActions?.table.updateConfig("columns", config);
+ setOpen(false);
+ };
+
+ return (
+ setOpen(false)}
+ title="Import"
+ steps={[
+ {
+ title: "Choose Columns",
+ description: (
+ <>
+
+ It looks like you already have data in this table. You can
+ import and view the data by setting up columns for this table.
+
+
+ Start by choosing which columns you want to display, then sort
+ your columns.
+
+ >
+ ),
+ content: (
+
+ ),
+ disableNext: Object.keys(config).length === 0,
+ },
+ {
+ title: "Rename Columns",
+ description:
+ "Rename your Rowy columns with user-friendly names. These changes will not update the field names in your database.",
+ content: (
+
+ ),
+ },
+ {
+ title: "Set Column Types",
+ description:
+ "Set the type of each column to display your data correctly. Some column types have been suggested based off your data.",
+ content: (
+
+ ),
+ },
+ {
+ title: "Preview",
+ description:
+ "Preview your data with your configured columns. You can change column types by clicking “Edit Type” from the column menu at any time.",
+ content: (
+
+ ),
+ },
+ ]}
+ onFinish={handleFinish}
+ />
+ );
+}
diff --git a/src/components/Wizards/ImportWizard/utils.ts b/src/components/Wizards/ImportWizard/utils.ts
new file mode 100644
index 000000000..65d41a891
--- /dev/null
+++ b/src/components/Wizards/ImportWizard/utils.ts
@@ -0,0 +1,92 @@
+import _isDate from "lodash/isDate";
+import _sortBy from "lodash/sortBy";
+
+import { FieldType } from "constants/fields";
+
+export const SELECTABLE_TYPES = [
+ FieldType.shortText,
+ FieldType.longText,
+ FieldType.email,
+ FieldType.phone,
+
+ FieldType.checkbox,
+ FieldType.number,
+ FieldType.percentage,
+
+ FieldType.date,
+ FieldType.dateTime,
+
+ FieldType.url,
+ FieldType.rating,
+
+ FieldType.singleSelect,
+ FieldType.multiSelect,
+
+ FieldType.json,
+ FieldType.code,
+
+ FieldType.richText,
+ FieldType.color,
+ FieldType.slider,
+];
+
+export const REGEX_EMAIL = /([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)/;
+export const REGEX_PHONE = /(([+][(]?[0-9]{1,3}[)]?)|([(]?[0-9]{4}[)]?))\s*[)]?[-\s\.]?[(]?[0-9]{1,3}[)]?([-\s\.]?[0-9]{3})([-\s\.]?[0-9]{3,4})/;
+export const REGEX_URL = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;
+export const REGEX_HTML = /<\/?[a-z][\s\S]*>/;
+
+const inferTypeFromValue = (value: any) => {
+ if (!value || typeof value === "function") return;
+
+ if (Array.isArray(value) && typeof value[0] === "string")
+ return FieldType.multiSelect;
+ if (typeof value === "boolean") return FieldType.checkbox;
+ if (_isDate(value)) return FieldType.dateTime;
+
+ if (typeof value === "object") {
+ if ("hex" in value && "rgb" in value) return FieldType.color;
+ if ("toDate" in value) return FieldType.dateTime;
+ return FieldType.json;
+ }
+
+ if (typeof value === "number") {
+ if (Math.abs(value) > 0 && Math.abs(value) < 1) return FieldType.percentage;
+ return FieldType.number;
+ }
+
+ if (typeof value === "string") {
+ if (REGEX_EMAIL.test(value)) return FieldType.email;
+ if (REGEX_PHONE.test(value)) return FieldType.phone;
+ if (REGEX_URL.test(value)) return FieldType.url;
+ if (REGEX_HTML.test(value)) return FieldType.richText;
+ if (value.length >= 50) return FieldType.longText;
+ return FieldType.shortText;
+ }
+
+ return;
+};
+
+export const suggestType = (data: { [key: string]: any }[], field: string) => {
+ const results: Record = {};
+
+ data.forEach((row) => {
+ const result = inferTypeFromValue(row[field]);
+ if (!result) return;
+ if (results[result] === undefined) results[result] = 1;
+ else results[result] += 1;
+ });
+
+ const sortedResults = _sortBy(Object.entries(results), 1).reverse();
+ if (!sortedResults || !sortedResults[0]) return FieldType.json;
+ const bestMatch = sortedResults[0][0];
+
+ if (bestMatch === FieldType.shortText) {
+ const values = data.map((row) => row[field]);
+ const uniqueValues = new Set(values);
+ const hasDuplicates = values.length !== uniqueValues.size;
+
+ if (hasDuplicates && uniqueValues.size < 30) return FieldType.singleSelect;
+ }
+
+ return bestMatch;
+};
diff --git a/src/components/Wizards/WizardDialog.tsx b/src/components/Wizards/WizardDialog.tsx
new file mode 100644
index 000000000..bdd0c45c4
--- /dev/null
+++ b/src/components/Wizards/WizardDialog.tsx
@@ -0,0 +1,269 @@
+import React, { useState } from "react";
+import clsx from "clsx";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import {
+ useTheme,
+ useMediaQuery,
+ Dialog,
+ DialogProps,
+ DialogTitle,
+ Grid,
+ Typography,
+ IconButton,
+ MobileStepper,
+ DialogContent,
+ Button,
+} from "@material-ui/core";
+import { alpha } from "@material-ui/core/styles";
+import CloseIcon from "@material-ui/icons/Close";
+import ChevronRightIcon from "@material-ui/icons/ChevronRight";
+import ChevronLeftIcon from "@material-ui/icons/ChevronLeft";
+
+import { SlideTransitionMui } from "components/Modal/SlideTransition";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: {
+ "--dialog-spacing": theme.spacing(3),
+ "--dialog-contents-spacing": theme.spacing(3),
+
+ [theme.breakpoints.down("md")]: {
+ "--dialog-spacing": theme.spacing(2),
+ },
+ },
+
+ paper: {
+ userSelect: "none",
+ overflowX: "hidden",
+
+ padding: "var(--dialog-spacing)",
+ paddingBottom: "var(--dialog-contents-spacing)",
+ },
+
+ closeButton: {
+ alignSelf: "flex-end",
+ margin:
+ "calc(var(--dialog-spacing) * -1) calc(var(--dialog-spacing) * -1) 0 0",
+ },
+
+ titleRow: { paddingBottom: "var(--dialog-spacing)" },
+ titleContainer: { padding: 0 },
+ title: {
+ ...theme.typography.h5,
+ [theme.breakpoints.down("md")]: theme.typography.h6,
+ },
+
+ stepper: {
+ padding: 0,
+ background: "none",
+ marginRight: theme.spacing(-10 / 8),
+
+ marginBottom: theme.spacing(-0.5),
+ [theme.breakpoints.down("md")]: { marginBottom: theme.spacing(-0.75) },
+ },
+ stepperButton: { padding: theme.spacing(0.5) },
+
+ stepperDot: {
+ margin: theme.spacing(0, 0.5),
+ backgroundColor: theme.palette.primary.main,
+ },
+ stepperDotActive: {
+ margin: theme.spacing(0, 0.5),
+ "& ~ $stepperDot": { backgroundColor: theme.palette.action.disabled },
+ },
+
+ content: {
+ padding: "0 var(--dialog-spacing)",
+ margin: "0 calc(var(--dialog-spacing) * -1)",
+
+ ...theme.typography.body1,
+
+ // https://codepen.io/evank/pen/wWbRNO
+ background: `
+ linear-gradient(
+ var(--bg-paper) 50%,
+ ${alpha(theme.palette.background.paper, 0)}
+ ),
+ linear-gradient(
+ ${alpha(theme.palette.background.paper, 0)},
+ var(--bg-paper) 50%
+ ) 0 100%,
+ linear-gradient(
+ to top, ${theme.palette.divider} 1px,
+ ${alpha(theme.palette.divider, 0)}
+ ),
+ linear-gradient(to top,
+ ${theme.palette.divider} 1px,
+ ${alpha(theme.palette.divider, 0)}
+ ) 0 calc(100% - 0.5px)`,
+ backgroundRepeat: "no-repeat",
+ backgroundColor: "var(--bg-paper)",
+ backgroundSize: "100% 2px, 100% 3px, 100% 1px, 100% 1px",
+ backgroundAttachment: "local, local, scroll, scroll",
+
+ "&:last-child": {
+ marginBottom: "calc(var(--dialog-contents-spacing) * -1)",
+ paddingBottom: "var(--dialog-contents-spacing)",
+ },
+
+ "& > * + *": { marginTop: "var(--dialog-contents-spacing)" },
+ },
+
+ actions: {
+ paddingTop: "var(--dialog-contents-spacing)",
+ "& button": { minWidth: 100 },
+ },
+ })
+);
+
+export interface IWizardDialogProps extends DialogProps {
+ title: string;
+ steps: {
+ title: string;
+ description?: React.ReactNode;
+ content: React.ReactNode;
+ disableNext?: boolean;
+ }[];
+ onFinish: () => void;
+}
+
+export default function WizardDialog({
+ title,
+ steps,
+ onFinish,
+ ...props
+}: IWizardDialogProps) {
+ const classes = useStyles();
+ const theme = useTheme();
+ const isXs = useMediaQuery(theme.breakpoints.down("sm"));
+
+ const [step, setStep] = useState(0);
+ const currentStep = steps[step];
+
+ const handleNext = () =>
+ step < steps.length - 1 ? setStep((s) => s + 1) : onFinish();
+ const handleBack = () =>
+ step > 0 ? setStep((s) => s - 1) : props.onClose?.({}, "escapeKeyDown");
+
+ return (
+
+
+
+
+
+
+
+
+
+ {title}
+ {currentStep.title && `: ${currentStep.title}`}
+
+
+
+
+
+
+
+
+ }
+ backButton={
+
+
+
+ }
+ />
+
+
+
+
+ {currentStep.description && (
+
+ {currentStep.description}
+
+ )}
+
+ {currentStep.content}
+
+
+
+
+ {step > 0 ? "Back" : "Cancel"}
+
+
+
+ {step === steps.length - 1 ? "Finish" : "Continue"}
+
+
+
+
+ );
+}
diff --git a/src/components/fields/Action/ActionFab.tsx b/src/components/fields/Action/ActionFab.tsx
new file mode 100644
index 000000000..f62ac3562
--- /dev/null
+++ b/src/components/fields/Action/ActionFab.tsx
@@ -0,0 +1,153 @@
+import { useContext, useState } from "react";
+import _get from "lodash/get";
+
+import { Fab, FabProps, CircularProgress } from "@material-ui/core";
+import PlayIcon from "@material-ui/icons/PlayArrow";
+import RefreshIcon from "@material-ui/icons/Refresh";
+import UndoIcon from "@material-ui/icons/Undo";
+
+import { useRowyContext } from "contexts/RowyContext";
+import { SnackContext } from "contexts/SnackContext";
+import { cloudFunction } from "firebase/callables";
+import { formatPath } from "utils/fns";
+import { useConfirmation } from "components/ConfirmationDialog";
+import { useActionParams } from "./FormDialog/Context";
+
+const replacer = (data: any) => (m: string, key: string) => {
+ const objKey = key.split(":")[0];
+ const defaultValue = key.split(":")[1] || "";
+ return _get(data, objKey, defaultValue);
+};
+
+const getStateIcon = (actionState) => {
+ switch (actionState) {
+ case "undo":
+ return ;
+ case "redo":
+ return ;
+ default:
+ return ;
+ }
+};
+
+export interface IActionFabProps extends Partial {
+ row: any;
+ column: any;
+ onSubmit: (value: any) => void;
+ value: any;
+ disabled: boolean;
+}
+
+export default function ActionFab({
+ row,
+ column,
+ onSubmit,
+ value,
+ disabled,
+ ...props
+}: IActionFabProps) {
+ const { requestConfirmation } = useConfirmation();
+ const { requestParams } = useActionParams();
+ const { tableState } = useRowyContext();
+ const { ref } = row;
+ const { config } = column as any;
+
+ const action = !value
+ ? "run"
+ : value.undo
+ ? "undo"
+ : value.redo
+ ? "redo"
+ : "";
+ const [isRunning, setIsRunning] = useState(false);
+ const snack = useContext(SnackContext);
+
+ const callableName: string =
+ (column as any).callableName ?? config.callableName ?? "actionScript";
+ const handleRun = (actionParams = null) => {
+ setIsRunning(true);
+
+ const data = {
+ ref: { path: ref.path, id: ref.id, tablePath: window.location.pathname },
+ column: { ...column, editor: undefined },
+ action,
+ schemaDocPath: formatPath(tableState?.tablePath ?? ""),
+ actionParams,
+ };
+ cloudFunction(
+ callableName,
+ data,
+ async (response) => {
+ const { message, cellValue, success } = response.data;
+ setIsRunning(false);
+ snack.open({
+ message: JSON.stringify(message),
+ variant: success ? "success" : "error",
+ });
+ if (cellValue && cellValue.status) {
+ await ref.update({
+ [column.key]: cellValue,
+ });
+ }
+ },
+ (error) => {
+ console.error("ERROR", callableName, error);
+ setIsRunning(false);
+ snack.open({ message: JSON.stringify(error), variant: "error" });
+ }
+ );
+ };
+ const hasRan = value && value.status;
+
+ const actionState: "run" | "undo" | "redo" = hasRan
+ ? value.undo
+ ? "undo"
+ : "redo"
+ : "run";
+
+ const needsParams = Array.isArray(config.params) && config.params.length > 0;
+ const needsConfirmation =
+ typeof config.confirmation === "string" && config.confirmation !== "";
+ return (
+
+ requestParams({
+ column,
+ row,
+ handleRun,
+ })
+ : needsConfirmation
+ ? () =>
+ requestConfirmation({
+ title: `${column.name} Confirmation`,
+ body: (actionState === "undo" && config.undoConfirmation
+ ? config.undoConfirmation
+ : config.confirmation
+ ).replace(/\{\{(.*?)\}\}/g, replacer(row)),
+ confirm: "Run",
+ handleConfirm: () => handleRun(),
+ })
+ : () => handleRun()
+ }
+ disabled={
+ isRunning ||
+ !!(
+ hasRan &&
+ (config.redo?.enabled ? false : !value.redo) &&
+ (config.undo?.enabled ? false : !value.undo)
+ ) ||
+ disabled
+ }
+ size="small"
+ {...props}
+ >
+ {isRunning ? (
+
+ ) : (
+ getStateIcon(actionState)
+ )}
+
+ );
+}
diff --git a/www/src/components/fields/Action/BasicCell.tsx b/src/components/fields/Action/BasicCell.tsx
similarity index 71%
rename from www/src/components/fields/Action/BasicCell.tsx
rename to src/components/fields/Action/BasicCell.tsx
index e5b57f6cf..61344b8cb 100644
--- a/www/src/components/fields/Action/BasicCell.tsx
+++ b/src/components/fields/Action/BasicCell.tsx
@@ -1,5 +1,5 @@
import { IBasicCellProps } from "../types";
export default function Action({ name, value }: IBasicCellProps) {
- return <>{value ? value.status : name}>;
+ return <>{value ? value.status : name}>;
}
diff --git a/www/src/components/fields/Action/FormDialog/Context.ts b/src/components/fields/Action/FormDialog/Context.ts
similarity index 91%
rename from www/src/components/fields/Action/FormDialog/Context.ts
rename to src/components/fields/Action/FormDialog/Context.ts
index 061026a85..1ac8ec576 100644
--- a/www/src/components/fields/Action/FormDialog/Context.ts
+++ b/src/components/fields/Action/FormDialog/Context.ts
@@ -1,7 +1,7 @@
import React, { useContext } from "react";
import { IActionParams, CONFIRMATION_EMPTY_STATE } from "./props";
const ActionParamsContext = React.createContext(
- CONFIRMATION_EMPTY_STATE
+ CONFIRMATION_EMPTY_STATE
);
export default ActionParamsContext;
diff --git a/src/components/fields/Action/FormDialog/Dialog.tsx b/src/components/fields/Action/FormDialog/Dialog.tsx
new file mode 100644
index 000000000..73573f9f0
--- /dev/null
+++ b/src/components/fields/Action/FormDialog/Dialog.tsx
@@ -0,0 +1,62 @@
+import * as yup from "yup";
+
+import { FormDialog } from "@antlerengineering/form-builder";
+
+const yupReducer = (validationConfig) => (acc, currKey) => {
+ if (validationConfig[currKey] !== null) {
+ const args = Array.isArray(validationConfig[currKey])
+ ? validationConfig[currKey]
+ : [validationConfig[currKey]];
+ return acc[currKey](...args);
+ } else return acc[currKey]();
+};
+const yupOrderKeys = (acc, currKey) => {
+ if (["string", "array"].includes(currKey)) return [currKey, ...acc];
+ else return [...acc, currKey];
+};
+
+const validationCompiler = (validation) =>
+ Object.keys(validation)
+ .reduce(yupOrderKeys, [])
+ .reduce(yupReducer(validation), yup);
+
+export default function ParamsDialog({
+ column,
+ handleRun,
+ open,
+ handleClose,
+}: any) {
+ /*
+ Refrence fields config
+ const _fields = [{
+ type: 'text',
+ name: "newCohort",
+ label: "New Cohort",
+ validation:{string:null,required:'needs to specific the cohort to new cohort'},
+ },
+ {
+ type: 'multiSelect',
+ name: "newCohortSelect",
+ label: "New Cohort",
+ options: ['SYD1','SYD3'],
+ validation:{array:null,required:'needs to specific the cohort to new cohort',max:[1,'only one cohort is allowed']},
+ }]
+*/
+ const fields = column.config.params.map((field) => ({
+ ...field,
+ validation: field.validation ? validationCompiler(field.validation) : null,
+ }));
+
+ if (!open) return null;
+
+ return (
+
+ );
+}
diff --git a/src/components/fields/Action/FormDialog/Provider.tsx b/src/components/fields/Action/FormDialog/Provider.tsx
new file mode 100644
index 000000000..75ef33fc4
--- /dev/null
+++ b/src/components/fields/Action/FormDialog/Provider.tsx
@@ -0,0 +1,39 @@
+import React, { useState } from "react";
+
+import { paramsDialogProps } from "./props";
+import Dialog from "./Dialog";
+import ActionParamsContext from "./Context";
+interface IActionParamsProviderProps {
+ children: React.ReactNode;
+}
+
+const ActionParamsProvider: React.FC = ({
+ children,
+}) => {
+ const [state, setState] = useState();
+ const [open, setOpen] = useState(false);
+ const handleClose = () => {
+ setState(undefined);
+ setOpen(false);
+ };
+ const requestParams = (props: paramsDialogProps) => {
+ setState(props);
+ setOpen(true);
+ };
+ return (
+
+ {children}
+
+ {state && }
+
+ );
+};
+
+export default ActionParamsProvider;
diff --git a/www/src/components/fields/Action/FormDialog/index.ts b/src/components/fields/Action/FormDialog/index.ts
similarity index 100%
rename from www/src/components/fields/Action/FormDialog/index.ts
rename to src/components/fields/Action/FormDialog/index.ts
diff --git a/src/components/fields/Action/FormDialog/props.ts b/src/components/fields/Action/FormDialog/props.ts
new file mode 100644
index 000000000..633536427
--- /dev/null
+++ b/src/components/fields/Action/FormDialog/props.ts
@@ -0,0 +1,19 @@
+export type paramsDialogProps =
+ | {
+ column: any;
+ row: any;
+ handleRun: (actionParams: any) => void;
+ }
+ | undefined;
+export interface IActionParams {
+ dialogProps?: paramsDialogProps;
+ handleClose: () => void;
+ open: boolean;
+ requestParams: (props: paramsDialogProps) => void;
+}
+export const CONFIRMATION_EMPTY_STATE = {
+ dialogProps: undefined,
+ open: false,
+ handleClose: () => {},
+ requestParams: () => {},
+};
diff --git a/src/components/fields/Action/Settings.tsx b/src/components/fields/Action/Settings.tsx
new file mode 100644
index 000000000..a00356eec
--- /dev/null
+++ b/src/components/fields/Action/Settings.tsx
@@ -0,0 +1,178 @@
+import { lazy, Suspense } from "react";
+import {
+ Typography,
+ TextField,
+ Switch,
+ FormControlLabel,
+ Divider,
+} from "@material-ui/core";
+import MultiSelect from "@antlerengineering/multiselect";
+import FieldSkeleton from "components/SideDrawer/Form/FieldSkeleton";
+import { useRowyContext } from "contexts/RowyContext";
+
+const CodeEditor = lazy(
+ () =>
+ import(
+ "components/Table/editors/CodeEditor" /* webpackChunkName: "CodeEditor" */
+ )
+);
+
+const Settings = ({ config, handleChange }) => {
+ const { tableState, roles } = useRowyContext();
+ const columnOptions = Object.values(tableState?.columns ?? {}).map((c) => ({
+ label: c.name,
+ value: c.key,
+ }));
+ return (
+ <>
+ Allowed roles
+
+ Authenticated user must have at least one of these to run the script
+
+
+
+ Required fields
+
+ All of the selected fields must have a value for the script to run
+
+
+
+
+ Confirmation Template
+
+ The action button will not ask for confirmation if this is left empty
+
+
+ {
+ handleChange("confirmation")(e.target.value);
+ }}
+ fullWidth
+ />
+
+ handleChange("isActionScript")(!Boolean(config.isActionScript))
+ }
+ name="actionScript"
+ />
+ }
+ label="Set as an action script"
+ />
+ {!Boolean(config.isActionScript) ? (
+ {
+ handleChange("callableName")(e.target.value);
+ }}
+ />
+ ) : (
+ <>
+ action script
+ }>
+ {
+ const validationKeys = Object.keys(param.validation);
+ if (validationKeys.includes("string")) {
+ return `static ${param.name}:string`;
+ } else if (validationKeys.includes("array")) {
+ return `static ${param.name}:any[]`;
+ } else return `static ${param.name}:any`;
+ }),
+ "}",
+ ],
+ ]}
+ handleChange={handleChange("script")}
+ />
+
+
+ handleChange("redo.enabled")(!Boolean(config.redo?.enabled))
+ }
+ name="redo toggle"
+ />
+ }
+ label="enable redo(reruns the same script)"
+ />
+
+ handleChange("undo.enabled")(!Boolean(config.undo?.enabled))
+ }
+ name="undo toggle"
+ />
+ }
+ label="enable undo"
+ />
+ {config["undo.enabled"] && (
+ <>
+
+ Undo Confirmation Template
+
+ {
+ handleChange("undo.confirmation")(e.target.value);
+ }}
+ fullWidth
+ />
+ Undo Action script
+ }>
+
+
+ >
+ )}
+ >
+ )}
+ >
+ );
+};
+export default Settings;
diff --git a/src/components/fields/Action/SideDrawerField.tsx b/src/components/fields/Action/SideDrawerField.tsx
new file mode 100644
index 000000000..79cc91ba0
--- /dev/null
+++ b/src/components/fields/Action/SideDrawerField.tsx
@@ -0,0 +1,78 @@
+import { Controller, useWatch } from "react-hook-form";
+import { ISideDrawerFieldProps } from "../types";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { Grid, Link } from "@material-ui/core";
+
+import ActionFab from "./ActionFab";
+import { useFieldStyles } from "components/SideDrawer/Form/utils";
+import { sanitiseCallableName, isUrl } from "utils/fns";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ labelGridItem: { width: `calc(100% - 56px - ${theme.spacing(2)})` },
+ label: {
+ whiteSpace: "normal",
+ width: "100%",
+ overflow: "hidden",
+ },
+ })
+);
+
+export default function Action({
+ column,
+ control,
+ docRef,
+ disabled,
+}: ISideDrawerFieldProps) {
+ const classes = useStyles();
+ const fieldClasses = useFieldStyles();
+
+ const row = useWatch({ control });
+
+ return (
+ {
+ const hasRan = value && value.status;
+
+ return (
+
+
+
+
+ {hasRan && isUrl(value.status) ? (
+
+ {value.status}
+
+ ) : hasRan ? (
+ value.status
+ ) : (
+ sanitiseCallableName(column.key)
+ )}
+
+
+
+
+
+
+
+
+ );
+ }}
+ />
+ );
+}
diff --git a/src/components/fields/Action/TableCell.tsx b/src/components/fields/Action/TableCell.tsx
new file mode 100644
index 000000000..52fcc7edd
--- /dev/null
+++ b/src/components/fields/Action/TableCell.tsx
@@ -0,0 +1,60 @@
+import { IHeavyCellProps } from "../types";
+import clsx from "clsx";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { Grid } from "@material-ui/core";
+
+import ActionFab from "./ActionFab";
+import { sanitiseCallableName, isUrl } from "utils/fns";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: { padding: theme.spacing(0, 0.375, 0, 1.5) },
+ labelContainer: { overflowX: "hidden" },
+ })
+);
+
+export default function Action({
+ column,
+ row,
+ value,
+ onSubmit,
+ disabled,
+}: IHeavyCellProps) {
+ const classes = useStyles();
+
+ const hasRan = value && value.status;
+
+ return (
+
+
+ {hasRan && isUrl(value.status) ? (
+
+ {value.status}
+
+ ) : hasRan ? (
+ value.status
+ ) : (
+ sanitiseCallableName(column.key)
+ )}
+
+
+
+
+
+
+ );
+}
diff --git a/src/components/fields/Action/index.tsx b/src/components/fields/Action/index.tsx
new file mode 100644
index 000000000..db4d3a68a
--- /dev/null
+++ b/src/components/fields/Action/index.tsx
@@ -0,0 +1,33 @@
+import { lazy } from "react";
+import { IFieldConfig, FieldType } from "components/fields/types";
+import withHeavyCell from "../_withTableCell/withHeavyCell";
+
+import ActionIcon from "@material-ui/icons/TouchAppOutlined";
+import BasicCell from "./BasicCell";
+import NullEditor from "components/Table/editors/NullEditor";
+
+const TableCell = lazy(
+ () => import("./TableCell" /* webpackChunkName: "TableCell-Action" */)
+);
+const SideDrawerField = lazy(
+ () =>
+ import("./SideDrawerField" /* webpackChunkName: "SideDrawerField-Action" */)
+);
+const Settings = lazy(
+ () => import("./Settings" /* webpackChunkName: "Settings-Action" */)
+);
+export const config: IFieldConfig = {
+ type: FieldType.action,
+ name: "Action",
+ dataType: "any",
+ initialValue: {},
+ icon: ,
+ description:
+ "A button with a pre-defined action. Triggers a Cloud Function. 3 different states: Disabled, Enabled, Active (Clicked). Supports Undo and Redo.",
+ TableCell: withHeavyCell(BasicCell, TableCell),
+ TableEditor: NullEditor as any,
+ SideDrawerField,
+ settings: Settings,
+ requireConfiguration: true,
+};
+export default config;
diff --git a/src/components/fields/Aggregate/Settings.tsx b/src/components/fields/Aggregate/Settings.tsx
new file mode 100644
index 000000000..647e414a2
--- /dev/null
+++ b/src/components/fields/Aggregate/Settings.tsx
@@ -0,0 +1,77 @@
+import { lazy, Suspense } from "react";
+import { Typography } from "@material-ui/core";
+import MultiSelect from "@antlerengineering/multiselect";
+import FieldSkeleton from "components/SideDrawer/Form/FieldSkeleton";
+import { FieldType } from "constants/fields";
+import FieldsDropdown from "components/Table/ColumnMenu/FieldsDropdown";
+import { useRowyContext } from "contexts/RowyContext";
+const CodeEditor = lazy(
+ () =>
+ import(
+ "components/Table/editors/CodeEditor" /* webpackChunkName: "CodeEditor" */
+ )
+);
+
+const Settings = ({ config, handleChange }) => {
+ const { tableState } = useRowyContext();
+
+ const columnOptions = Object.values(tableState?.columns ?? {})
+ .filter((column) => column.type === FieldType.subTable)
+ .map((c) => ({ label: c.name, value: c.key }));
+ return (
+ <>
+
+ Aggergate script
+ }>
+
+
+
+ Field type of the output
+
+ ![
+ FieldType.derivative,
+ FieldType.aggregate,
+ FieldType.subTable,
+ FieldType.action,
+ ].includes(f)
+ )}
+ onChange={(newType: any) => {
+ handleChange("renderFieldType")(newType.target.value);
+ }}
+ />
+ >
+ );
+};
+export default Settings;
diff --git a/src/components/fields/Aggregate/index.tsx b/src/components/fields/Aggregate/index.tsx
new file mode 100644
index 000000000..ff92761df
--- /dev/null
+++ b/src/components/fields/Aggregate/index.tsx
@@ -0,0 +1,21 @@
+import { IFieldConfig, FieldType } from "components/fields/types";
+import withBasicCell from "../_withTableCell/withBasicCell";
+
+import AggregateIcon from "@material-ui/icons/LayersOutlined";
+import BasicCell from "../_BasicCell/BasicCellNull";
+import NullEditor from "components/Table/editors/NullEditor";
+
+export const config: IFieldConfig = {
+ type: FieldType.aggregate,
+ name: "Aggregate",
+ dataType: "string",
+ initialValue: "",
+ initializable: false,
+ icon: ,
+ description:
+ "Value aggregated from a specified sub-table of the row. Displayed using any other field type. Requires Cloud Function setup.",
+ TableCell: withBasicCell(BasicCell),
+ TableEditor: NullEditor as any,
+ SideDrawerField: BasicCell as any,
+};
+export default config;
diff --git a/src/components/fields/Checkbox/SideDrawerField.tsx b/src/components/fields/Checkbox/SideDrawerField.tsx
new file mode 100644
index 000000000..94ab6e498
--- /dev/null
+++ b/src/components/fields/Checkbox/SideDrawerField.tsx
@@ -0,0 +1,71 @@
+import clsx from "clsx";
+import { Controller } from "react-hook-form";
+import { ISideDrawerFieldProps } from "../types";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { ButtonBase, FormControlLabel, Switch } from "@material-ui/core";
+
+import { useFieldStyles } from "components/SideDrawer/Form/utils";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: { padding: 0 },
+
+ formControlLabel: {
+ margin: 0,
+ width: "100%",
+ display: "flex",
+
+ padding: theme.spacing(0, 0.25, 0, 1.5),
+ },
+
+ label: {
+ ...theme.typography.body2,
+ flexGrow: 1,
+ whiteSpace: "normal",
+ },
+ })
+);
+
+export default function Checkbox({
+ column,
+ control,
+ disabled,
+}: ISideDrawerFieldProps) {
+ const classes = useStyles();
+ const fieldClasses = useFieldStyles();
+
+ return (
+ {
+ const handleChange = (event: React.ChangeEvent) => {
+ onChange(event.target.checked);
+ };
+
+ return (
+
+
+ }
+ label={column.name}
+ labelPlacement="start"
+ classes={{ root: classes.formControlLabel, label: classes.label }}
+ />
+
+ );
+ }}
+ />
+ );
+}
diff --git a/src/components/fields/Checkbox/TableCell.tsx b/src/components/fields/Checkbox/TableCell.tsx
new file mode 100644
index 000000000..5efb0a245
--- /dev/null
+++ b/src/components/fields/Checkbox/TableCell.tsx
@@ -0,0 +1,77 @@
+import { IHeavyCellProps } from "../types";
+import _get from "lodash/get";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { FormControlLabel, Switch } from "@material-ui/core";
+
+import Confirmation from "components/Confirmation";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: {
+ marginLeft: 0,
+ marginRight: theme.spacing(-1),
+ width: `calc(100% + ${theme.spacing(1)})`,
+ },
+
+ label: {
+ font: "inherit",
+ letterSpacing: "inherit",
+
+ flexGrow: 1,
+ width: "calc(100% - 58px)",
+ overflowX: "hidden",
+ },
+ })
+);
+
+const replacer = (data: any) => (m: string, key: string) => {
+ const objKey = key.split(":")[0];
+ const defaultValue = key.split(":")[1] || "";
+ return _get(data, objKey, defaultValue);
+};
+
+export default function Checkbox({
+ row,
+ column,
+ value,
+ onSubmit,
+ disabled,
+}: IHeavyCellProps) {
+ const classes = useStyles();
+
+ let component = (
+ onSubmit(!value)}
+ disabled={disabled}
+ color="success"
+ />
+ );
+
+ if (column?.config?.confirmation)
+ component = (
+
+ {component}
+
+ );
+
+ return (
+
+ );
+}
diff --git a/src/components/fields/Checkbox/index.tsx b/src/components/fields/Checkbox/index.tsx
new file mode 100644
index 000000000..51b1b74af
--- /dev/null
+++ b/src/components/fields/Checkbox/index.tsx
@@ -0,0 +1,36 @@
+import { lazy } from "react";
+import { IFieldConfig, FieldType } from "components/fields/types";
+import withHeavyCell from "../_withTableCell/withHeavyCell";
+
+import CheckboxIcon from "@material-ui/icons/ToggleOnOutlined";
+import BasicCell from "../_BasicCell/BasicCellName";
+import NullEditor from "components/Table/editors/NullEditor";
+
+const TableCell = lazy(
+ () => import("./TableCell" /* webpackChunkName: "TableCell-Checkbox" */)
+);
+const SideDrawerField = lazy(
+ () =>
+ import(
+ "./SideDrawerField" /* webpackChunkName: "SideDrawerField-Checkbox" */
+ )
+);
+
+export const config: IFieldConfig = {
+ type: FieldType.checkbox,
+ name: "Toggle",
+ dataType: "boolean",
+ initialValue: false,
+ initializable: true,
+ icon: ,
+ description: "Either toggled on or off. Toggled off by default.",
+ TableCell: withHeavyCell(BasicCell, TableCell),
+ TableEditor: NullEditor as any,
+ csvImportParser: (value: string) => {
+ if (["YES", "TRUE", "1"].includes(value.toUpperCase())) return true;
+ else if (["NO", "FALSE", "0"].includes(value.toUpperCase())) return false;
+ else return null;
+ },
+ SideDrawerField,
+};
+export default config;
diff --git a/src/components/fields/Code/BasicCell.tsx b/src/components/fields/Code/BasicCell.tsx
new file mode 100644
index 000000000..3ab98eaf6
--- /dev/null
+++ b/src/components/fields/Code/BasicCell.tsx
@@ -0,0 +1,24 @@
+import { IBasicCellProps } from "../types";
+
+import { useTheme } from "@material-ui/core";
+
+export default function Code({ value }: IBasicCellProps) {
+ const theme = useTheme();
+
+ return (
+
+ {value}
+
+ );
+}
diff --git a/src/components/fields/Code/SideDrawerField.tsx b/src/components/fields/Code/SideDrawerField.tsx
new file mode 100644
index 000000000..dc864ceb6
--- /dev/null
+++ b/src/components/fields/Code/SideDrawerField.tsx
@@ -0,0 +1,48 @@
+import { Controller } from "react-hook-form";
+import { ISideDrawerFieldProps } from "../types";
+
+import CodeEditor from "components/CodeEditor";
+import { makeStyles, createStyles } from "@material-ui/styles";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ wrapper: {
+ border: "1px solid",
+ borderColor:
+ theme.palette.mode === "light"
+ ? "rgba(0, 0, 0, 0.09)"
+ : "rgba(255, 255, 255, 0.09)",
+
+ borderRadius: theme.shape.borderRadius,
+ overflow: "hidden",
+ },
+ })
+);
+
+export default function Code({
+ control,
+ column,
+ disabled,
+}: ISideDrawerFieldProps) {
+ const classes = useStyles();
+
+ return (
+ (
+
+ )}
+ />
+ );
+}
diff --git a/www/src/components/fields/Code/index.tsx b/src/components/fields/Code/index.tsx
similarity index 53%
rename from www/src/components/fields/Code/index.tsx
rename to src/components/fields/Code/index.tsx
index 033f4057a..ecf27f3fd 100644
--- a/www/src/components/fields/Code/index.tsx
+++ b/src/components/fields/Code/index.tsx
@@ -7,20 +7,20 @@ import BasicCell from "./BasicCell";
import withSideDrawerEditor from "components/Table/editors/withSideDrawerEditor";
const SideDrawerField = lazy(
- () =>
- import("./SideDrawerField" /* webpackChunkName: "SideDrawerField-Code" */)
+ () =>
+ import("./SideDrawerField" /* webpackChunkName: "SideDrawerField-Code" */)
);
export const config: IFieldConfig = {
- type: FieldType.code,
- name: "Code",
- dataType: "string",
- initialValue: "",
- initializable: true,
- icon: ,
- description: "Raw code editable with Monaco Editor.",
- TableCell: withBasicCell(BasicCell),
- TableEditor: withSideDrawerEditor(BasicCell),
- SideDrawerField,
+ type: FieldType.code,
+ name: "Code",
+ dataType: "string",
+ initialValue: "",
+ initializable: true,
+ icon: ,
+ description: "Raw code editable with Monaco Editor.",
+ TableCell: withBasicCell(BasicCell),
+ TableEditor: withSideDrawerEditor(BasicCell),
+ SideDrawerField,
};
export default config;
diff --git a/src/components/fields/Color/InlineCell.tsx b/src/components/fields/Color/InlineCell.tsx
new file mode 100644
index 000000000..ff098bdd8
--- /dev/null
+++ b/src/components/fields/Color/InlineCell.tsx
@@ -0,0 +1,59 @@
+import React from "react";
+import clsx from "clsx";
+import { IPopoverInlineCellProps } from "../types";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { Grid, ButtonBase } from "@material-ui/core";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: {
+ font: "inherit",
+ color: "inherit !important",
+ letterSpacing: "inherit",
+ textAlign: "inherit",
+
+ padding: theme.spacing(0, 1),
+ },
+
+ colorIndicator: {
+ width: 20,
+ height: 20,
+
+ boxShadow: `0 0 0 1px ${theme.palette.text.disabled} inset`,
+ borderRadius: (theme.shape.borderRadius as number) / 2,
+ },
+ })
+);
+
+export const Color = React.forwardRef(function Color(
+ { value, showPopoverCell, disabled }: IPopoverInlineCellProps,
+ ref: React.Ref
+) {
+ const classes = useStyles();
+
+ return (
+ showPopoverCell(true)}
+ ref={ref}
+ disabled={disabled}
+ >
+
+
+
+
+
+ {value?.hex}
+
+
+ );
+});
+export default Color;
diff --git a/www/src/components/fields/Color/PopoverCell.tsx b/src/components/fields/Color/PopoverCell.tsx
similarity index 51%
rename from www/src/components/fields/Color/PopoverCell.tsx
rename to src/components/fields/Color/PopoverCell.tsx
index 3d0989956..e7d4d6a69 100644
--- a/www/src/components/fields/Color/PopoverCell.tsx
+++ b/src/components/fields/Color/PopoverCell.tsx
@@ -2,9 +2,9 @@ import { IPopoverCellProps } from "../types";
import { ChromePicker } from "react-color";
export default function Color({ value, onSubmit }: IPopoverCellProps) {
- const handleChangeComplete = (color) => onSubmit(color);
+ const handleChangeComplete = (color) => onSubmit(color);
- return (
-
- );
+ return (
+
+ );
}
diff --git a/src/components/fields/Color/SideDrawerField.tsx b/src/components/fields/Color/SideDrawerField.tsx
new file mode 100644
index 000000000..130c10029
--- /dev/null
+++ b/src/components/fields/Color/SideDrawerField.tsx
@@ -0,0 +1,93 @@
+import { useState } from "react";
+import { Controller } from "react-hook-form";
+import { ISideDrawerFieldProps } from "../types";
+import { ChromePicker } from "react-color";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { Grid, ButtonBase, Typography, Collapse } from "@material-ui/core";
+
+// import { useFieldStyles } from "components/SideDrawer/Form/utils";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: {
+ height: 56,
+ cursor: "pointer",
+ textAlign: "left",
+ borderRadius: theme.shape.borderRadius,
+
+ backgroundColor:
+ theme.palette.mode === "light"
+ ? "rgba(0, 0, 0, 0.09)"
+ : "rgba(255, 255, 255, 0.09)",
+ margin: 0,
+ width: "100%",
+ padding: theme.spacing(0, 0.75),
+ },
+
+ colorIndicator: {
+ width: 20,
+ height: 20,
+ marginLeft: 2,
+
+ boxShadow: `0 0 0 1px ${theme.palette.text.disabled} inset`,
+ borderRadius: theme.shape.borderRadius,
+ },
+ })
+);
+
+export default function Color({
+ column,
+ control,
+ disabled,
+}: ISideDrawerFieldProps) {
+ const classes = useStyles();
+ // const fieldClasses = useFieldStyles();
+
+ const [showPicker, setShowPicker] = useState(false);
+ const toggleOpen = () => setShowPicker((s) => !s);
+
+ return (
+ (
+ <>
+ {
+ toggleOpen();
+ onBlur();
+ }}
+ component={ButtonBase}
+ focusRipple
+ disabled={disabled}
+ >
+
+
+
+
+
+
+ {value?.hex ?? "Choose a color…"}
+
+
+
+
+
+
+
+ >
+ )}
+ />
+ );
+}
diff --git a/src/components/fields/Color/index.tsx b/src/components/fields/Color/index.tsx
new file mode 100644
index 000000000..cb3107ada
--- /dev/null
+++ b/src/components/fields/Color/index.tsx
@@ -0,0 +1,32 @@
+import { lazy } from "react";
+import { IFieldConfig, FieldType } from "components/fields/types";
+import withPopoverCell from "../_withTableCell/withPopoverCell";
+
+import ColorIcon from "@material-ui/icons/Colorize";
+import BasicCell from "../_BasicCell/BasicCellNull";
+import InlineCell from "./InlineCell";
+import NullEditor from "components/Table/editors/NullEditor";
+
+const PopoverCell = lazy(
+ () => import("./PopoverCell" /* webpackChunkName: "PopoverCell-Color" */)
+);
+const SideDrawerField = lazy(
+ () =>
+ import("./SideDrawerField" /* webpackChunkName: "SideDrawerField-Color" */)
+);
+
+export const config: IFieldConfig = {
+ type: FieldType.color,
+ name: "Color",
+ dataType: "Record",
+ initialValue: {},
+ initializable: true,
+ icon: ,
+ description: "Visual color picker. Supports Hex, RGBA, HSLA.",
+ TableCell: withPopoverCell(BasicCell, InlineCell, PopoverCell, {
+ anchorOrigin: { horizontal: "left", vertical: "bottom" },
+ }),
+ TableEditor: NullEditor as any,
+ SideDrawerField,
+};
+export default config;
diff --git a/src/components/fields/ConnectService/ConnectServiceSelect/PopupContents.tsx b/src/components/fields/ConnectService/ConnectServiceSelect/PopupContents.tsx
new file mode 100644
index 000000000..28de0a996
--- /dev/null
+++ b/src/components/fields/ConnectService/ConnectServiceSelect/PopupContents.tsx
@@ -0,0 +1,202 @@
+import React, { useEffect, useState } from "react";
+import clsx from "clsx";
+import { useDebouncedCallback } from "use-debounce";
+import _get from "lodash/get";
+
+import {
+ Button,
+ Checkbox,
+ Divider,
+ Grid,
+ InputAdornment,
+ List,
+ ListItemIcon,
+ ListItemText,
+ MenuItem,
+ TextField,
+ Typography,
+ Radio,
+} from "@material-ui/core";
+import SearchIcon from "@material-ui/icons/Search";
+
+import { IConnectServiceSelectProps } from ".";
+import useStyles from "./styles";
+import Loading from "components/Loading";
+
+export interface IPopupContentsProps
+ extends Omit {}
+
+// TODO: Implement infinite scroll here
+export default function PopupContents({
+ value = [],
+ onChange,
+ config,
+ docRef,
+}: IPopupContentsProps) {
+ const url = config.url;
+ const titleKey = config.titleKey ?? config.primaryKey;
+ const subtitleKey = config.subtitleKey;
+ const resultsKey = config.resultsKey;
+ const primaryKey = config.primaryKey;
+ const multiple = Boolean(config.multiple);
+
+ const classes = useStyles();
+
+ // Webservice search query
+ const [query, setQuery] = useState("");
+ // Webservice response
+ const [response, setResponse] = useState(null);
+
+ const [docData, setDocData] = useState(null);
+ useEffect(() => {
+ docRef.get().then((d) => setDocData(d.data()));
+ }, []);
+
+ const hits: any["hits"] = _get(response, resultsKey) ?? [];
+ const [search] = useDebouncedCallback(
+ async (query: string) => {
+ if (!docData) return;
+ if (!url) return;
+ const uri = new URL(url),
+ params = { q: query };
+ Object.keys(params).forEach((key) =>
+ uri.searchParams.append(key, params[key])
+ );
+
+ const resp = await fetch(uri.toString(), {
+ method: "POST",
+ body: JSON.stringify(docData),
+ headers: { "content-type": "application/json" },
+ });
+
+ const jsonBody = await resp.json();
+ setResponse(jsonBody);
+ },
+ 1000,
+ { leading: true }
+ );
+
+ useEffect(() => {
+ search(query);
+ }, [query, docData]);
+
+ if (!response) return ;
+
+ const select = (hit: any) => () => {
+ if (multiple) onChange([...value, hit]);
+ else onChange([hit]);
+ };
+ const deselect = (hit: any) => () => {
+ if (multiple)
+ onChange(value.filter((v) => v[primaryKey] !== hit[primaryKey]));
+ else onChange([]);
+ };
+
+ const selectedValues = value?.map((item) => _get(item, primaryKey));
+
+ const clearSelection = () => onChange([]);
+
+ return (
+
+
+ setQuery(e.target.value)}
+ fullWidth
+ variant="filled"
+ margin="dense"
+ label="Search items"
+ className={classes.noMargins}
+ InputProps={{
+ endAdornment: (
+
+
+
+ ),
+ }}
+ onClick={(e) => e.stopPropagation()}
+ onKeyDown={(e) => e.stopPropagation()}
+ />
+
+
+
+
+ {hits.map((hit) => {
+ const isSelected =
+ selectedValues.indexOf(_get(hit, primaryKey)) !== -1;
+ return (
+
+
+
+ {multiple ? (
+
+ ) : (
+
+ )}
+
+
+
+
+
+ );
+ })}
+
+
+
+ {multiple && (
+
+
+
+ {value?.length} of {hits?.length}
+
+
+
+ Clear Selection
+
+
+
+ )}
+
+ );
+}
diff --git a/src/components/fields/ConnectService/ConnectServiceSelect/index.tsx b/src/components/fields/ConnectService/ConnectServiceSelect/index.tsx
new file mode 100644
index 000000000..c6e79e10c
--- /dev/null
+++ b/src/components/fields/ConnectService/ConnectServiceSelect/index.tsx
@@ -0,0 +1,76 @@
+import { Suspense } from "react";
+import clsx from "clsx";
+
+import { TextField, TextFieldProps } from "@material-ui/core";
+
+import useStyles from "./styles";
+import Loading from "components/Loading";
+import ErrorBoundary from "components/ErrorBoundary";
+import PopupContents from "./PopupContents";
+
+export type ServiceValue = {
+ value: string;
+ [prop: string]: any;
+};
+
+export interface IConnectServiceSelectProps {
+ value: ServiceValue[];
+ onChange: (value: ServiceValue[]) => void;
+ config: {
+ displayKey: string;
+ [key: string]: any;
+ };
+ editable?: boolean;
+ /** Optional style overrides for root MUI `TextField` component */
+ className?: string;
+ /** Override any props of the root MUI `TextField` component */
+ TextFieldProps?: Partial;
+ docRef: firebase.default.firestore.DocumentReference;
+ disabled?: boolean;
+}
+
+export default function ConnectServiceSelect({
+ value = [],
+ className,
+ TextFieldProps = {},
+ disabled,
+ ...props
+}: IConnectServiceSelectProps) {
+ const classes = useStyles();
+
+ const sanitisedValue = Array.isArray(value) ? value : [];
+
+ return (
+ `${(value as any[]).length} selected`,
+ displayEmpty: true,
+ classes: { root: classes.selectRoot },
+ ...TextFieldProps.SelectProps,
+ // Must have this set to prevent MUI transforming `value`
+ // prop for this component to a comma-separated string
+ MenuProps: {
+ classes: { paper: classes.paper, list: classes.menuChild },
+ MenuListProps: { disablePadding: true },
+ anchorOrigin: { vertical: "bottom", horizontal: "center" },
+ transformOrigin: { vertical: "top", horizontal: "center" },
+ ...TextFieldProps.SelectProps?.MenuProps,
+ },
+ }}
+ disabled={disabled}
+ >
+
+ }>
+
+
+
+
+ );
+}
diff --git a/src/components/fields/ConnectService/ConnectServiceSelect/styles.ts b/src/components/fields/ConnectService/ConnectServiceSelect/styles.ts
new file mode 100644
index 000000000..b567a3b36
--- /dev/null
+++ b/src/components/fields/ConnectService/ConnectServiceSelect/styles.ts
@@ -0,0 +1,83 @@
+import { makeStyles, createStyles } from "@material-ui/styles";
+
+export const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: { minWidth: 200 },
+ selectRoot: { paddingRight: theme.spacing(4) },
+
+ paper: { overflow: "hidden", maxHeight: "calc(100% - 48px)" },
+ menuChild: {
+ padding: `0 ${theme.spacing(2)}`,
+ minWidth: 340,
+ // Need to set fixed height here so popup is positioned correctly
+ height: 340,
+ },
+
+ grid: { outline: 0 },
+
+ noMargins: { margin: 0 },
+
+ searchRow: { marginTop: theme.spacing(2) },
+
+ listRow: {
+ background: `${theme.palette.background.paper} no-repeat`,
+ position: "relative",
+ margin: theme.spacing(0, -2),
+ maxWidth: `calc(100% + ${theme.spacing(4)})`,
+
+ "&::before, &::after": {
+ content: '""',
+ position: "absolute",
+ top: 0,
+ left: 0,
+ right: 0,
+ zIndex: 9,
+
+ display: "block",
+ height: 16,
+
+ background: `linear-gradient(to bottom, #fff, rgba(255, 255, 255, 0))`,
+ },
+
+ "&::after": {
+ top: "auto",
+ bottom: 0,
+ background: `linear-gradient(to top, #fff, rgba(255, 255, 255, 0))`,
+ },
+ },
+ list: () => {
+ let maxHeightDeductions = 0;
+ maxHeightDeductions -= 64; // search box
+ maxHeightDeductions -= 48; // multiple
+ maxHeightDeductions += 8; // footer padding
+
+ return {
+ padding: theme.spacing(2, 0),
+ overflowY: "auto" as "auto",
+ // height: `calc(340px - ${-maxHeightDeductions}px)`,
+ height: 340 + maxHeightDeductions,
+ };
+ },
+
+ checkboxContainer: { minWidth: theme.spacing(36 / 8) },
+ checkbox: {
+ padding: theme.spacing(6 / 8, 9 / 8),
+ "&:hover": { background: "transparent" },
+ },
+
+ divider: { margin: theme.spacing(0, 2, 0, 6.5) },
+
+ footerRow: { marginBottom: theme.spacing(2) },
+ selectedRow: {
+ "$listRow + &": { marginTop: -theme.spacing(1) },
+ "$footerRow + &": { marginTop: -theme.spacing(2) },
+
+ marginBottom: 0,
+ "& > div": { height: 48 },
+ },
+ selectAllButton: { marginRight: -theme.spacing(1) },
+ selectedNum: { fontFeatureSettings: '"tnum"' },
+ })
+);
+
+export default useStyles;
diff --git a/src/components/fields/ConnectService/InlineCell.tsx b/src/components/fields/ConnectService/InlineCell.tsx
new file mode 100644
index 000000000..f3198edab
--- /dev/null
+++ b/src/components/fields/ConnectService/InlineCell.tsx
@@ -0,0 +1,83 @@
+import React from "react";
+import clsx from "clsx";
+import { IPopoverInlineCellProps } from "../types";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { ButtonBase, Grid, Chip } from "@material-ui/core";
+import ArrowDropDownIcon from "@material-ui/icons/ArrowDropDown";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: {
+ height: "100%",
+ padding: theme.spacing(0, 1, 0, 1.5),
+
+ font: "inherit",
+ color: "inherit !important",
+ letterSpacing: "inherit",
+ textAlign: "inherit",
+ justifyContent: "flex-start",
+ },
+
+ value: {
+ flex: 1,
+ maxWidth: `calc(100% - 24px + 4px)`,
+ overflow: "hidden",
+ marginRight: 0,
+ },
+ chip: {
+ display: "flex",
+ cursor: "inherit",
+ },
+ chipLabel: { whiteSpace: "nowrap" },
+
+ icon: {
+ display: "block",
+ color: theme.palette.action.active,
+ },
+ disabled: {
+ color: theme.palette.action.disabled,
+ },
+ })
+);
+
+export const ConnectService = React.forwardRef(function ConnectService(
+ { value, showPopoverCell, disabled, column }: IPopoverInlineCellProps,
+ ref: React.Ref
+) {
+ const classes = useStyles();
+ const config = column.config ?? {};
+
+ return (
+ showPopoverCell(true)}
+ ref={ref}
+ disabled={disabled}
+ >
+
+ {Array.isArray(value) &&
+ value.map((doc: any) => (
+
+
+
+ ))}
+
+
+
+
+ );
+});
+export default ConnectService;
diff --git a/src/components/fields/ConnectService/PopoverCell.tsx b/src/components/fields/ConnectService/PopoverCell.tsx
new file mode 100644
index 000000000..585912a62
--- /dev/null
+++ b/src/components/fields/ConnectService/PopoverCell.tsx
@@ -0,0 +1,38 @@
+import { IPopoverCellProps } from "../types";
+
+import ConnectServiceSelect from "./ConnectServiceSelect";
+
+export default function ConnectService({
+ value,
+ onSubmit,
+ column,
+ parentRef,
+ showPopoverCell,
+ disabled,
+ docRef,
+}: IPopoverCellProps) {
+ const config = column.config ?? {};
+ if (!config) return null;
+
+ return (
+ showPopoverCell(false),
+ },
+ }}
+ />
+ );
+}
diff --git a/src/components/fields/ConnectService/Settings.tsx b/src/components/fields/ConnectService/Settings.tsx
new file mode 100644
index 000000000..ee3c9435b
--- /dev/null
+++ b/src/components/fields/ConnectService/Settings.tsx
@@ -0,0 +1,65 @@
+import { TextField, FormControlLabel, Switch } from "@material-ui/core";
+
+export default function Settings({ config, handleChange }) {
+ return (
+ <>
+ {
+ handleChange("url")(e.target.value);
+ }}
+ />
+ {
+ handleChange("resultsKey")(e.target.value);
+ }}
+ />
+ {
+ handleChange("primaryKey")(e.target.value);
+ }}
+ />
+ {
+ handleChange("titleKey")(e.target.value);
+ }}
+ />
+ {
+ handleChange("subtitleKey")(e.target.value);
+ }}
+ />
+ handleChange("multiple")(!Boolean(config.multiple))}
+ name="select-multiple"
+ />
+ }
+ label="Enable multiple item selection"
+ />
+ >
+ );
+}
diff --git a/src/components/fields/ConnectService/SideDrawerField.tsx b/src/components/fields/ConnectService/SideDrawerField.tsx
new file mode 100644
index 000000000..69592d787
--- /dev/null
+++ b/src/components/fields/ConnectService/SideDrawerField.tsx
@@ -0,0 +1,77 @@
+import { Controller } from "react-hook-form";
+import { ISideDrawerFieldProps } from "../types";
+import { get } from "lodash";
+
+import { useTheme, Grid, Chip } from "@material-ui/core";
+
+import ConnectServiceSelect from "./ConnectServiceSelect";
+
+export default function ConnectService({
+ column,
+ control,
+ disabled,
+ docRef,
+}: ISideDrawerFieldProps) {
+ const theme = useTheme();
+
+ const config = column.config ?? {};
+ const displayKey = config.titleKey ?? config.primaryKey;
+
+ return (
+ {
+ const handleDelete = (hit: any) => () => {
+ // if (multiple)
+ onChange(
+ value.filter(
+ (v) => get(v, config.primaryKey) !== get(hit, config.primaryKey)
+ )
+ );
+ // else form.setFieldValue(field.name, []);
+ };
+
+ return (
+ <>
+ {!disabled && (
+ `${value?.length ?? 0} selected`,
+ // },
+ }}
+ />
+ )}
+
+ {Array.isArray(value) && (
+
+ {value.map((snapshot) => (
+
+
+
+ ))}
+
+ )}
+ >
+ );
+ }}
+ />
+ );
+}
diff --git a/src/components/fields/ConnectService/index.tsx b/src/components/fields/ConnectService/index.tsx
new file mode 100644
index 000000000..d5fe05334
--- /dev/null
+++ b/src/components/fields/ConnectService/index.tsx
@@ -0,0 +1,40 @@
+import { lazy } from "react";
+import { IFieldConfig, FieldType } from "components/fields/types";
+import withPopoverCell from "../_withTableCell/withPopoverCell";
+
+import ConnectServiceIcon from "@material-ui/icons/Http";
+import BasicCell from "../_BasicCell/BasicCellNull";
+import InlineCell from "./InlineCell";
+import NullEditor from "components/Table/editors/NullEditor";
+
+const PopoverCell = lazy(
+ () =>
+ import("./PopoverCell" /* webpackChunkName: "PopoverCell-ConnectService" */)
+);
+const SideDrawerField = lazy(
+ () =>
+ import(
+ "./SideDrawerField" /* webpackChunkName: "SideDrawerField-ConnectService" */
+ )
+);
+const Settings = lazy(
+ () => import("./Settings" /* webpackChunkName: "Settings-ConnectService" */)
+);
+
+export const config: IFieldConfig = {
+ type: FieldType.connectService,
+ name: "Connect Service",
+ dataType: "{ docPath: string; snapshot: Record; }",
+ initialValue: [],
+ icon: ,
+ description:
+ "Connects to an external web service to fetch a list of results.",
+ TableCell: withPopoverCell(BasicCell, InlineCell, PopoverCell, {
+ anchorOrigin: { horizontal: "left", vertical: "bottom" },
+ transparent: true,
+ }),
+ TableEditor: NullEditor as any,
+ SideDrawerField,
+ settings: Settings,
+};
+export default config;
diff --git a/src/components/fields/ConnectService/utils.ts b/src/components/fields/ConnectService/utils.ts
new file mode 100644
index 000000000..265db5081
--- /dev/null
+++ b/src/components/fields/ConnectService/utils.ts
@@ -0,0 +1,4 @@
+export const sanitiseValue = (value: any) => {
+ if (value === undefined || value === null || value === "") return [];
+ else return value as string[];
+};
diff --git a/src/components/fields/ConnectTable/ConnectTableSelect.tsx b/src/components/fields/ConnectTable/ConnectTableSelect.tsx
new file mode 100644
index 000000000..5c3f983dd
--- /dev/null
+++ b/src/components/fields/ConnectTable/ConnectTableSelect.tsx
@@ -0,0 +1,224 @@
+import { useState, useEffect } from "react";
+import { useDebounce } from "use-debounce";
+import useAlgolia from "use-algolia";
+import _find from "lodash/find";
+import _get from "lodash/get";
+import _pick from "lodash/pick";
+
+import MultiSelect, { MultiSelectProps } from "@antlerengineering/multiselect";
+import Loading from "components/Loading";
+import { getAlgoliaSearchKey } from "../../../firebase/callables";
+import createPersistedState from "use-persisted-state";
+const useAlgoliaSearchKeys = createPersistedState("algolia-search");
+
+export type ConnectTableValue = {
+ docPath: string;
+ snapshot: Record;
+};
+
+const replacer = (data: any) => (m: string, key: string) => {
+ const objKey = key.split(":")[0];
+ const defaultValue = key.split(":")[1] || "";
+ return _get(data, objKey, defaultValue);
+};
+
+export interface IConnectTableSelectProps {
+ value: ConnectTableValue[];
+ onChange: (value: ConnectTableValue[]) => void;
+ column: any;
+ config: {
+ filters: string;
+ primaryKeys: string[];
+ secondaryKeys?: string[];
+ snapshotFields?: string[];
+ trackedFields?: string[];
+ multiple?: boolean;
+ searchLabel?: string;
+ [key: string]: any;
+ };
+ disabled?: boolean;
+ /** Optional style overrides for root MUI `TextField` component */
+ className?: string;
+ row: any;
+ /** Override any props of the root MUI `TextField` component */
+ TextFieldProps?: MultiSelectProps["TextFieldProps"];
+ onClose?: MultiSelectProps["onClose"];
+ /** Load the Algolia index before the MultiSelect onOpen function is triggered */
+ loadBeforeOpen?: boolean;
+}
+
+export default function ConnectTableSelect({
+ value = [],
+ onChange,
+ column,
+ row,
+ config,
+ disabled,
+ className,
+ TextFieldProps = {},
+ onClose,
+ loadBeforeOpen,
+}: IConnectTableSelectProps) {
+ // Store a local copy of the value so the dropdown doesn’t automatically close
+ // when the user selects a new item and we allow for multiple selections
+ const [localValue, setLocalValue] = useState(
+ Array.isArray(value) ? value : []
+ );
+ const filters = config.filters
+ ? config.filters.replace(/\{\{(.*?)\}\}/g, replacer(row))
+ : "";
+ const algoliaIndex = config.index;
+
+ const [algoliaSearchKeys, setAlgoliaSearchKeys] = useAlgoliaSearchKeys(
+ {}
+ );
+ const [algoliaState, requestDispatch, , setAlgoliaConfig] = useAlgolia(
+ process.env.REACT_APP_ALGOLIA_APP_ID!,
+ process.env.REACT_APP_ALGOLIA_SEARCH_API_KEY ?? "",
+ // Don’t choose the index until the user opens the dropdown if !loadBeforeOpen
+ loadBeforeOpen ? algoliaIndex : "",
+ { filters }
+ );
+
+ const setAlgoliaSearchKey = async (algoliaIndex: string) => {
+ const requestedAt = Date.now() / 1000;
+ if (
+ algoliaSearchKeys &&
+ (algoliaSearchKeys?.[algoliaIndex] as any)?.key &&
+ requestedAt <
+ (algoliaSearchKeys?.[algoliaIndex] as any).requestedAt + 3600
+ ) {
+ //'use existing key'
+ setAlgoliaConfig({
+ indexName: algoliaIndex,
+ searchKey: (algoliaSearchKeys?.[algoliaIndex] as any).key,
+ });
+ } else {
+ //'get new key'
+ const resp = await getAlgoliaSearchKey(algoliaIndex);
+ const key = resp.data.data;
+ if (key) {
+ const newKey = {
+ key,
+ requestedAt,
+ };
+ setAlgoliaSearchKeys(
+ algoliaSearchKeys
+ ? { ...algoliaSearchKeys, [algoliaIndex]: newKey }
+ : { [algoliaIndex]: newKey }
+ );
+ setAlgoliaConfig({ indexName: algoliaIndex, searchKey: key });
+ }
+ }
+ };
+
+ useEffect(() => {
+ if (!process.env.REACT_APP_ALGOLIA_SEARCH_API_KEY)
+ setAlgoliaSearchKey(algoliaIndex);
+ }, [algoliaIndex]);
+
+ const options = algoliaState.hits.map((hit) => ({
+ label: config.primaryKeys?.map((key: string) => hit[key]).join(" "),
+ value: hit.objectID,
+ }));
+
+ // Pass a list of objectIDs to MultiSelect
+ const sanitisedValue = localValue.map(
+ (item) => item.docPath.split("/")[item.docPath.split("/").length - 1]
+ );
+
+ const handleChange = (_newValue) => {
+ // Ensure we return an array
+ const newValue = Array.isArray(_newValue)
+ ? _newValue
+ : _newValue !== null
+ ? [_newValue]
+ : [];
+
+ // Calculate new value
+ const newLocalValue = newValue.map((objectID) => {
+ // If this objectID is already in the previous value, use that previous
+ // value’s snapshot (in case it points to an object not in the current
+ // Algolia query)
+ const existingMatch = _find(localValue, {
+ docPath: `${algoliaIndex}/${objectID}`,
+ });
+ if (existingMatch) return existingMatch;
+
+ // If this is a completely new selection, grab the snapshot from the
+ // current Algolia query
+ const match = _find(algoliaState.hits, { objectID });
+ const { _highlightResult, ...snapshot } = match;
+
+ // Use snapshotFields to limit snapshots
+ let partialSnapshot = snapshot;
+ if (
+ Array.isArray(config.snapshotFields) &&
+ config.snapshotFields.length > 0
+ )
+ partialSnapshot = _pick(snapshot, config.snapshotFields);
+
+ return {
+ snapshot: partialSnapshot,
+ docPath: `${algoliaIndex}/${snapshot.objectID}`,
+ };
+ });
+
+ // If !multiple, we MUST change the value (bypassing localValue),
+ // otherwise `setLocalValue` won’t be called in time for the new
+ // `localValue` to be read by `handleSave`
+ if (config.multiple === false) onChange(newLocalValue);
+ // Otherwise, `setLocalValue` until user closes dropdown
+ else setLocalValue(newLocalValue);
+ };
+
+ // Save when user closes dropdown
+ const handleSave = () => {
+ if (config.multiple !== false) onChange(localValue);
+ if (onClose) onClose();
+ };
+ // Change MultiSelect input field to search Algolia directly
+ const [search, setSearch] = useState("");
+ const [debouncedSearch] = useDebounce(search, 1000);
+ useEffect(() => {
+ requestDispatch({ query: debouncedSearch });
+ }, [debouncedSearch]);
+
+ return (
+ {
+ setAlgoliaConfig({
+ indexName: algoliaIndex,
+ });
+ requestDispatch({ filters });
+ }}
+ onClose={handleSave}
+ options={options}
+ TextFieldProps={{
+ className,
+ hiddenLabel: true,
+ ...TextFieldProps,
+ }}
+ label={column?.name}
+ labelPlural={config.searchLabel}
+ multiple={(config.multiple ?? true) as any}
+ {...({
+ AutocompleteProps: {
+ loading: algoliaState.loading,
+ loadingText: ,
+ inputValue: search,
+ onInputChange: (_, value, reason) => {
+ if (reason === "input") setSearch(value);
+ },
+ filterOptions: () => options,
+ },
+ } as any)}
+ countText={`${localValue.length} of ${
+ algoliaState.response?.nbHits ?? "?"
+ }`}
+ disabled={disabled}
+ />
+ );
+}
diff --git a/src/components/fields/ConnectTable/InlineCell.tsx b/src/components/fields/ConnectTable/InlineCell.tsx
new file mode 100644
index 000000000..b66ec4a57
--- /dev/null
+++ b/src/components/fields/ConnectTable/InlineCell.tsx
@@ -0,0 +1,86 @@
+import React from "react";
+import clsx from "clsx";
+import { IPopoverInlineCellProps } from "../types";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { ButtonBase, Grid, Chip } from "@material-ui/core";
+import ArrowDropDownIcon from "@material-ui/icons/ArrowDropDown";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: {
+ height: "100%",
+ padding: theme.spacing(0, 1, 0, 1.5),
+
+ font: "inherit",
+ color: "inherit !important",
+ letterSpacing: "inherit",
+ textAlign: "inherit",
+ justifyContent: "flex-start",
+ },
+
+ value: {
+ flex: 1,
+ maxWidth: `calc(100% - 24px + 4px)`,
+ overflow: "hidden",
+ marginRight: 0,
+ },
+ chip: {
+ display: "flex",
+ cursor: "inherit",
+ },
+ chipLabel: { whiteSpace: "nowrap" },
+
+ icon: {
+ display: "block",
+ color: theme.palette.action.active,
+ },
+ disabled: {
+ color: theme.palette.action.disabled,
+ },
+ })
+);
+
+export const ConnectTable = React.forwardRef(function ConnectTable(
+ { value, showPopoverCell, disabled, column }: IPopoverInlineCellProps,
+ ref: React.Ref
+) {
+ const classes = useStyles();
+ const config = column.config ?? {};
+
+ return (
+ showPopoverCell(true)}
+ ref={ref}
+ disabled={disabled}
+ >
+
+ {Array.isArray(value) &&
+ value.map((doc: any) => (
+
+ doc.snapshot[key])
+ .join(" ")}
+ // size="small"
+ className={classes.chip}
+ />
+
+ ))}
+
+
+
+
+ );
+});
+export default ConnectTable;
diff --git a/src/components/fields/ConnectTable/PopoverCell.tsx b/src/components/fields/ConnectTable/PopoverCell.tsx
new file mode 100644
index 000000000..b4202b8c5
--- /dev/null
+++ b/src/components/fields/ConnectTable/PopoverCell.tsx
@@ -0,0 +1,40 @@
+import { IPopoverCellProps } from "../types";
+
+import ConnectTableSelect from "./ConnectTableSelect";
+
+export default function ConnectTable({
+ value,
+ onSubmit,
+ column,
+ parentRef,
+ showPopoverCell,
+ row,
+ disabled,
+}: IPopoverCellProps) {
+ const config = column.config ?? {};
+ if (!config || !config.primaryKeys) return null;
+
+ return (
+ showPopoverCell(false)}
+ loadBeforeOpen
+ />
+ );
+}
diff --git a/src/components/fields/ConnectTable/Settings.tsx b/src/components/fields/ConnectTable/Settings.tsx
new file mode 100644
index 000000000..355ecbfa3
--- /dev/null
+++ b/src/components/fields/ConnectTable/Settings.tsx
@@ -0,0 +1,87 @@
+import { useEffect, useState } from "react";
+import { ISettingsProps } from "../types";
+import _sortBy from "lodash/sortBy";
+
+import { TextField } from "@material-ui/core";
+import Subheading from "components/Table/ColumnMenu/Subheading";
+import MultiSelect from "@antlerengineering/multiselect";
+
+import { FieldType } from "constants/fields";
+import { db } from "../../../firebase";
+import { useRowyContext } from "contexts/RowyContext";
+
+export default function Settings({ handleChange, config }: ISettingsProps) {
+ const { tables } = useRowyContext();
+ const tableOptions = _sortBy(
+ tables?.map((t) => ({
+ label: `${t.section} - ${t.name}`,
+ value: t.collection,
+ })) ?? [],
+ "label"
+ );
+
+ const [columns, setColumns] = useState<
+ { value: string; label: string; type: FieldType }[]
+ >([]);
+ const getColumns = async (table) => {
+ const tableConfigDoc = await db
+ .doc(`_rowy_/settings/schema/${table}`)
+ .get();
+ const tableConfig = tableConfigDoc.data();
+ if (tableConfig && tableConfig.columns)
+ setColumns(
+ Object.values(tableConfig.columns).map((c: any) => ({
+ label: c.name,
+ value: c.key,
+ type: c.type,
+ }))
+ );
+ };
+ useEffect(() => {
+ if (config.index) {
+ getColumns(config.index);
+ }
+ }, [config.index]);
+
+ return (
+ <>
+ Table Connect Config
+
+ {
+ handleChange("filters")(e.target.value);
+ }}
+ />
+
+ [FieldType.shortText, FieldType.singleSelect].includes(c.type)
+ )}
+ onChange={handleChange("primaryKeys")}
+ />
+ ![FieldType.subTable].includes(c.type))}
+ onChange={handleChange("snapshotFields")}
+ />
+ ![FieldType.subTable].includes(c.type))}
+ onChange={handleChange("trackedFields")}
+ />
+ >
+ );
+}
diff --git a/src/components/fields/ConnectTable/SideDrawerField.tsx b/src/components/fields/ConnectTable/SideDrawerField.tsx
new file mode 100644
index 000000000..55a39643e
--- /dev/null
+++ b/src/components/fields/ConnectTable/SideDrawerField.tsx
@@ -0,0 +1,73 @@
+import { Controller } from "react-hook-form";
+import { ISideDrawerFieldProps } from "../types";
+
+import { useTheme, Grid, Chip } from "@material-ui/core";
+
+import ConnectTableSelect from "./ConnectTableSelect";
+
+export default function ConnectTable({
+ column,
+ control,
+ disabled,
+}: ISideDrawerFieldProps) {
+ const theme = useTheme();
+
+ const config = column.config ?? {};
+
+ return (
+ {
+ const handleDelete = (hit: any) => () => {
+ // if (multiple)
+ onChange(value.filter((v) => v.snapshot.objectID !== hit.objectID));
+ // else form.setFieldValue(field.name, []);
+ };
+
+ return (
+ <>
+ {!disabled && (
+ `${value?.length ?? 0} selected`,
+ },
+ }}
+ />
+ )}
+
+ {Array.isArray(value) && (
+
+ {value.map(({ snapshot }) => (
+
+ snapshot[key])
+ .join(" ")}
+ onDelete={disabled ? undefined : handleDelete(snapshot)}
+ />
+
+ ))}
+
+ )}
+ >
+ );
+ }}
+ />
+ );
+}
diff --git a/src/components/fields/ConnectTable/index.tsx b/src/components/fields/ConnectTable/index.tsx
new file mode 100644
index 000000000..5152b24c6
--- /dev/null
+++ b/src/components/fields/ConnectTable/index.tsx
@@ -0,0 +1,40 @@
+import { lazy } from "react";
+import { IFieldConfig, FieldType } from "components/fields/types";
+import withPopoverCell from "../_withTableCell/withPopoverCell";
+
+import ConnectTableIcon from "assets/icons/ConnectTable";
+import BasicCell from "../_BasicCell/BasicCellNull";
+import InlineCell from "./InlineCell";
+import NullEditor from "components/Table/editors/NullEditor";
+
+const PopoverCell = lazy(
+ () =>
+ import("./PopoverCell" /* webpackChunkName: "PopoverCell-ConnectTable" */)
+);
+const SideDrawerField = lazy(
+ () =>
+ import(
+ "./SideDrawerField" /* webpackChunkName: "SideDrawerField-ConnectTable" */
+ )
+);
+const Settings = lazy(
+ () => import("./Settings" /* webpackChunkName: "Settings-ConnectTable" */)
+);
+
+export const config: IFieldConfig = {
+ type: FieldType.connectTable,
+ name: "Connect Table",
+ dataType: "{ docPath: string; snapshot: Record; }",
+ initialValue: [],
+ icon: ,
+ description:
+ "Connects to an existing table to fetch a snapshot of values from a row. Requires Algolia integration.",
+ TableCell: withPopoverCell(BasicCell, InlineCell, PopoverCell, {
+ anchorOrigin: { horizontal: "left", vertical: "bottom" },
+ transparent: true,
+ }),
+ TableEditor: NullEditor as any,
+ SideDrawerField,
+ settings: Settings,
+};
+export default config;
diff --git a/src/components/fields/ConnectTable/utils.ts b/src/components/fields/ConnectTable/utils.ts
new file mode 100644
index 000000000..265db5081
--- /dev/null
+++ b/src/components/fields/ConnectTable/utils.ts
@@ -0,0 +1,4 @@
+export const sanitiseValue = (value: any) => {
+ if (value === undefined || value === null || value === "") return [];
+ else return value as string[];
+};
diff --git a/src/components/fields/Date/BasicCell.tsx b/src/components/fields/Date/BasicCell.tsx
new file mode 100644
index 000000000..c872c9336
--- /dev/null
+++ b/src/components/fields/Date/BasicCell.tsx
@@ -0,0 +1,22 @@
+import { IBasicCellProps } from "../types";
+import { format } from "date-fns";
+import { DATE_FORMAT } from "constants/dates";
+import { DateIcon } from ".";
+
+export default function Date_({ value }: IBasicCellProps) {
+ if (!!value && "toDate" in value) {
+ try {
+ const formatted = format(value.toDate(), DATE_FORMAT);
+ return (
+ <>
+
+ {formatted}
+ >
+ );
+ } catch (e) {
+ return null;
+ }
+ }
+
+ return null;
+}
diff --git a/src/components/fields/Date/Settings.tsx b/src/components/fields/Date/Settings.tsx
new file mode 100644
index 000000000..db813dac0
--- /dev/null
+++ b/src/components/fields/Date/Settings.tsx
@@ -0,0 +1,21 @@
+import { ISettingsProps } from "../types";
+
+import Subheading from "components/Table/ColumnMenu/Subheading";
+import MultiSelect from "@antlerengineering/multiselect";
+import { DATE_FORMAT } from "constants/dates";
+
+export default function Settings({ handleChange, config }: ISettingsProps) {
+ return (
+ <>
+ Date Config
+
+ >
+ );
+}
diff --git a/src/components/fields/Date/SideDrawerField.tsx b/src/components/fields/Date/SideDrawerField.tsx
new file mode 100644
index 000000000..cd490d3cc
--- /dev/null
+++ b/src/components/fields/Date/SideDrawerField.tsx
@@ -0,0 +1,58 @@
+import { Controller } from "react-hook-form";
+import { ISideDrawerFieldProps } from "../types";
+
+import { useTheme } from "@material-ui/core";
+import LocalizationProvider from "@material-ui/lab/LocalizationProvider";
+import AdapterDateFns from "@material-ui/lab/AdapterDateFns";
+
+import { transformValue, sanitizeValue } from "./utils";
+
+export interface IDateProps extends ISideDrawerFieldProps {}
+
+export default function Date_({ column, control }: IDateProps) {
+ const theme = useTheme();
+
+ return (
+
+ {
+ const transformedValue = transformValue(value);
+
+ const handleChange = (date: Date | null) => {
+ const sanitized = sanitizeValue(date);
+ if (sanitized === undefined) return;
+ onChange(sanitized);
+ };
+
+ return <>>;
+ // TODO:
+ // (
+ //
+ // )}
+ // value={transformedValue}
+ // onChange={handleChange}
+ // disabled={disabled}
+ // />
+ }}
+ />
+
+ );
+}
diff --git a/src/components/fields/Date/TableCell.tsx b/src/components/fields/Date/TableCell.tsx
new file mode 100644
index 000000000..238d17b77
--- /dev/null
+++ b/src/components/fields/Date/TableCell.tsx
@@ -0,0 +1,105 @@
+import { IHeavyCellProps } from "../types";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+
+import { transformValue } from "./utils";
+
+// import DateFnsUtils from "@date-io/date-fns";
+// import {
+// MuiPickersUtilsProvider,
+// KeyboardDatePicker,
+// DatePickerProps,
+// } from "@material-ui/pickers";
+
+import { useRowyContext } from "contexts/RowyContext";
+import BasicCell from "./BasicCell";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: { height: "100%" },
+ inputBase: {
+ height: "100%",
+ color: "inherit",
+ },
+
+ inputAdornment: {
+ height: "100%",
+ marginLeft: theme.spacing(1) + 1,
+ marginRight: theme.spacing(0.25),
+ },
+
+ input: {
+ ...theme.typography.body2,
+ fontSize: "0.75rem",
+ color: "inherit",
+ height: "100%",
+ padding: theme.spacing(1.5, 0),
+ },
+
+ dateTabIcon: {
+ color: theme.palette.primary.contrastText,
+ },
+
+ disabledCell: {
+ color: theme.palette.text.disabled,
+ display: "flex",
+ alignItems: "center",
+ },
+ })
+);
+
+export default function Date_({ column, value }: IHeavyCellProps) {
+ const classes = useStyles();
+ const {} = useRowyContext();
+
+ const transformedValue = transformValue(value);
+
+ // const [handleDateChange] = useDebouncedCallback(
+ // (date) => {
+ // const sanitized = sanitizeValue(date);
+ // if (sanitized === undefined) return;
+
+ // onSubmit(sanitized);
+ // if (dataGridRef?.current?.selectCell)
+ // dataGridRef.current.selectCell({ rowIdx, idx: column.idx });
+ // },
+ // 500
+ // );
+
+ // if (disabled)
+ return (
+
+
+
+ );
+
+ // return (
+ //
+ // e.stopPropagation()}
+ // format={column.config?.format ?? DATE_FORMAT}
+ // fullWidth
+ // clearable
+ // keyboardIcon={ }
+ // className={clsx("cell-collapse-padding", classes.root)}
+ // inputVariant="standard"
+ // InputProps={{
+ // disableUnderline: true,
+ // classes: { root: classes.inputBase, input: classes.input },
+ // }}
+ // InputAdornmentProps={{
+ // position: "start",
+ // classes: { root: classes.inputAdornment },
+ // }}
+ // KeyboardButtonProps={{
+ // size: "small",
+ // classes: { root: !disabled ? "row-hover-iconButton" : undefined },
+ // }}
+ // DialogProps={{ onClick: (e) => e.stopPropagation() }}
+ // disabled={disabled}
+ // />
+ //
+ // );
+}
diff --git a/src/components/fields/Date/index.tsx b/src/components/fields/Date/index.tsx
new file mode 100644
index 000000000..ec053b64b
--- /dev/null
+++ b/src/components/fields/Date/index.tsx
@@ -0,0 +1,41 @@
+import { lazy } from "react";
+import { IFieldConfig, FieldType } from "components/fields/types";
+import withHeavyCell from "../_withTableCell/withHeavyCell";
+import { parse, format } from "date-fns";
+import { DATE_FORMAT } from "constants/dates";
+import DateIcon from "@material-ui/icons/TodayOutlined";
+import BasicCell from "./BasicCell";
+import NullEditor from "components/Table/editors/NullEditor";
+
+const TableCell = lazy(
+ () => import("./TableCell" /* webpackChunkName: "TableCell-Date" */)
+);
+const SideDrawerField = lazy(
+ () =>
+ import("./SideDrawerField" /* webpackChunkName: "SideDrawerField-Date" */)
+);
+const Settings = lazy(
+ () => import("./Settings" /* webpackChunkName: "Settings-ConnectTable" */)
+);
+
+export const config: IFieldConfig = {
+ type: FieldType.date,
+ name: "Date",
+ dataType: "firebase.firestore.Timestamp",
+ initialValue: null,
+ initializable: true,
+ icon: ,
+ description:
+ "Date displayed and input by default as YYYY/MM/DD or input using a picker module.",
+ TableCell: withHeavyCell(BasicCell, TableCell),
+ TableEditor: NullEditor as any,
+ SideDrawerField,
+ settings: Settings,
+ csvImportParser: (value, config) =>
+ parse(value, config?.format ?? DATE_FORMAT, new Date()),
+ csvExportFormatter: (value: any, config?: any) =>
+ format(value.toDate(), config?.format ?? DATE_FORMAT),
+};
+export default config;
+
+export { DateIcon };
diff --git a/src/components/fields/Date/utils.ts b/src/components/fields/Date/utils.ts
new file mode 100644
index 000000000..5994c686e
--- /dev/null
+++ b/src/components/fields/Date/utils.ts
@@ -0,0 +1,11 @@
+export const transformValue = (value: any) => {
+ if (typeof value === "number") return new Date(value);
+ if (value && "toDate" in value) return value.toDate();
+ if (value !== undefined) return value;
+ return null;
+};
+
+export const sanitizeValue = (value: Date | null) => {
+ if (isNaN(value?.valueOf() ?? 0)) return undefined;
+ return value;
+};
diff --git a/src/components/fields/DateTime/BasicCell.tsx b/src/components/fields/DateTime/BasicCell.tsx
new file mode 100644
index 000000000..48feb66a2
--- /dev/null
+++ b/src/components/fields/DateTime/BasicCell.tsx
@@ -0,0 +1,22 @@
+import { IBasicCellProps } from "../types";
+import { format } from "date-fns";
+import { DATE_TIME_FORMAT } from "constants/dates";
+import { DateTimeIcon } from ".";
+
+export default function DateTime({ value }: IBasicCellProps) {
+ if (!!value && "toDate" in value) {
+ try {
+ const formatted = format(value.toDate(), DATE_TIME_FORMAT);
+ return (
+ <>
+
+ {formatted}
+ >
+ );
+ } catch (e) {
+ return null;
+ }
+ }
+
+ return null;
+}
diff --git a/src/components/fields/DateTime/SideDrawerField.tsx b/src/components/fields/DateTime/SideDrawerField.tsx
new file mode 100644
index 000000000..e2cc01e13
--- /dev/null
+++ b/src/components/fields/DateTime/SideDrawerField.tsx
@@ -0,0 +1,74 @@
+import { ISideDrawerFieldProps } from "../types";
+
+import { useTheme } from "@material-ui/core";
+// import {
+// KeyboardDateTimePicker,
+// KeyboardDateTimePickerProps,
+// } from "@material-ui/pickers";
+
+// import { MuiPickersUtilsProvider } from "@material-ui/pickers";
+// import DateFnsUtils from "@date-io/date-fns";
+
+export interface IDateTimeProps extends ISideDrawerFieldProps {
+ // ,Omit<
+ // KeyboardDateTimePickerProps,
+ // "name" | "onChange" | "value" | "disabled"
+ // >
+}
+
+export default function DateTime({}: IDateTimeProps) {
+ const theme = useTheme();
+
+ return <>>;
+
+ // TODO: return (
+ // {
+ // const transformedValue = transformValue(value);
+
+ // const handleChange = (date: Date | null) => {
+ // const sanitized = sanitizeValue(date);
+ // if (sanitized === undefined) return;
+ // onChange(sanitized);
+ // };
+
+ // return (
+ //
+ // }
+ // {...props}
+ // value={transformedValue}
+ // onChange={handleChange}
+ // onBlur={onBlur}
+ // label=""
+ // hiddenLabel
+ // id={`sidedrawer-field-${column.key}`}
+ // dateRangeIcon={
+ //
+ // }
+ // timeIcon={
+ //
+ // }
+ // disabled={disabled}
+ // />
+ //
+ // );
+ // }}
+ // />
+ // );
+}
diff --git a/src/components/fields/DateTime/TableCell.tsx b/src/components/fields/DateTime/TableCell.tsx
new file mode 100644
index 000000000..367ba2b75
--- /dev/null
+++ b/src/components/fields/DateTime/TableCell.tsx
@@ -0,0 +1,105 @@
+import { IHeavyCellProps } from "../types";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+
+import { transformValue } from "../Date/utils";
+
+// import {
+// MuiPickersUtilsProvider,
+// KeyboardDateTimePicker,
+// DatePickerProps,
+// } from "@material-ui/pickers";
+
+import { useRowyContext } from "contexts/RowyContext";
+import BasicCell from "./BasicCell";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: { height: "100%" },
+ inputBase: {
+ height: "100%",
+ color: "inherit",
+ },
+
+ inputAdornment: {
+ height: "100%",
+ marginLeft: theme.spacing(1) + 1,
+ marginRight: theme.spacing(0.25),
+ },
+
+ input: {
+ ...theme.typography.body2,
+ fontSize: "0.75rem",
+ color: "inherit",
+ height: "100%",
+ padding: theme.spacing(1.5, 0),
+ },
+
+ dateTabIcon: {
+ color: theme.palette.primary.contrastText,
+ },
+
+ disabledCell: {
+ color: theme.palette.text.disabled,
+ display: "flex",
+ alignItems: "center",
+ },
+ })
+);
+
+export default function DateTime({ column, value }: IHeavyCellProps) {
+ const classes = useStyles();
+ const {} = useRowyContext();
+
+ const transformedValue = transformValue(value);
+
+ // const [handleDateChange] = useDebouncedCallback(
+ // (date) => {
+ // const sanitized = sanitizeValue(date);
+ // if (sanitized === undefined) return;
+
+ // onSubmit(sanitized);
+ // if (dataGridRef?.current?.selectCell)
+ // dataGridRef.current.selectCell({ rowIdx, idx: column.idx });
+ // },
+ // 500
+ // );
+
+ // if (disabled)
+ return (
+
+
+
+ );
+
+ // return (
+ //
+ // e.stopPropagation()}
+ // format={DATE_TIME_FORMAT}
+ // fullWidth
+ // clearable
+ // keyboardIcon={ }
+ // className={clsx("cell-collapse-padding", classes.root)}
+ // inputVariant="standard"
+ // InputProps={{
+ // disableUnderline: true,
+ // classes: { root: classes.inputBase, input: classes.input },
+ // }}
+ // InputAdornmentProps={{
+ // position: "start",
+ // classes: { root: classes.inputAdornment },
+ // }}
+ // KeyboardButtonProps={{
+ // size: "small",
+ // classes: { root: "row-hover-iconButton" },
+ // }}
+ // DialogProps={{ onClick: (e) => e.stopPropagation() }}
+ // dateRangeIcon={ }
+ // timeIcon={ }
+ // />
+ //
+ // );
+}
diff --git a/src/components/fields/DateTime/index.tsx b/src/components/fields/DateTime/index.tsx
new file mode 100644
index 000000000..0caf793a5
--- /dev/null
+++ b/src/components/fields/DateTime/index.tsx
@@ -0,0 +1,36 @@
+import { lazy } from "react";
+import { IFieldConfig, FieldType } from "components/fields/types";
+import withHeavyCell from "../_withTableCell/withHeavyCell";
+import { parseJSON } from "date-fns";
+
+import DateTimeIcon from "@material-ui/icons/AccessTime";
+import BasicCell from "./BasicCell";
+import NullEditor from "components/Table/editors/NullEditor";
+
+const TableCell = lazy(
+ () => import("./TableCell" /* webpackChunkName: "TableCell-DateTime" */)
+);
+const SideDrawerField = lazy(
+ () =>
+ import(
+ "./SideDrawerField" /* webpackChunkName: "SideDrawerField-DateTime" */
+ )
+);
+
+export const config: IFieldConfig = {
+ type: FieldType.dateTime,
+ name: "Time & Date",
+ dataType: "firebase.firestore.Timestamp",
+ initialValue: null,
+ initializable: true,
+ icon: ,
+ description:
+ "Time and Date can be written as YYYY/MM/DD hh:mm (am/pm) or input using a picker module.",
+ TableCell: withHeavyCell(BasicCell, TableCell),
+ TableEditor: NullEditor as any,
+ SideDrawerField,
+ csvImportParser: (value) => parseJSON(value).getTime(),
+};
+export default config;
+
+export { DateTimeIcon };
diff --git a/src/components/fields/Derivative/Settings.tsx b/src/components/fields/Derivative/Settings.tsx
new file mode 100644
index 000000000..a59d1b89f
--- /dev/null
+++ b/src/components/fields/Derivative/Settings.tsx
@@ -0,0 +1,70 @@
+import { lazy, Suspense } from "react";
+import { Typography, Grid } from "@material-ui/core";
+import MultiSelect from "@antlerengineering/multiselect";
+import FieldSkeleton from "components/SideDrawer/Form/FieldSkeleton";
+import { FieldType } from "constants/fields";
+import FieldsDropdown from "components/Table/ColumnMenu/FieldsDropdown";
+import { useRowyContext } from "contexts/RowyContext";
+import CodeEditorHelper from "components/CodeEditorHelper";
+
+import WIKI_LINKS from "constants/wikiLinks";
+
+const CodeEditor = lazy(
+ () =>
+ import(
+ "components/Table/editors/CodeEditor" /* webpackChunkName: "CodeEditor" */
+ )
+);
+
+const Settings = ({ config, handleChange }) => {
+ const { tableState } = useRowyContext();
+ if (!tableState?.columns) return <>>;
+ const columnOptions = Object.values(tableState.columns)
+ .filter((column) => column.type !== FieldType.subTable)
+ .map((c) => ({ label: c.name, value: c.key }));
+ return (
+ <>
+
+
+ listener Fields
+
+
+ Changes to these fields will trigger the evaluation of the column.
+
+
+
+ Output Field type
+
+ ![
+ FieldType.derivative,
+ FieldType.aggregate,
+ FieldType.subTable,
+ FieldType.action,
+ ].includes(f)
+ )}
+ onChange={(newType: any) => {
+ handleChange("renderFieldType")(newType.target.value);
+ }}
+ />
+
+
+ derivative script
+
+ }>
+
+
+ >
+ );
+};
+export default Settings;
diff --git a/src/components/fields/Derivative/index.tsx b/src/components/fields/Derivative/index.tsx
new file mode 100644
index 000000000..0077e3655
--- /dev/null
+++ b/src/components/fields/Derivative/index.tsx
@@ -0,0 +1,24 @@
+import { IFieldConfig, FieldType } from "components/fields/types";
+import withBasicCell from "../_withTableCell/withBasicCell";
+
+import DerivativeIcon from "assets/icons/Derivative";
+import BasicCell from "../_BasicCell/BasicCellNull";
+import NullEditor from "components/Table/editors/NullEditor";
+import Settings from "./Settings";
+
+export const config: IFieldConfig = {
+ type: FieldType.derivative,
+ name: "Derivative",
+ dataType: "string",
+ initialValue: "",
+ initializable: true,
+ icon: ,
+ requireConfiguration: true,
+ description:
+ "Value derived from the rest of the row’s values. Displayed using any other field type. Requires Cloud Function setup.",
+ TableCell: withBasicCell(BasicCell),
+ TableEditor: NullEditor as any,
+ SideDrawerField: BasicCell as any,
+ settings: Settings,
+};
+export default config;
diff --git a/src/components/fields/Duration/SideDrawerField.tsx b/src/components/fields/Duration/SideDrawerField.tsx
new file mode 100644
index 000000000..743a97993
--- /dev/null
+++ b/src/components/fields/Duration/SideDrawerField.tsx
@@ -0,0 +1,32 @@
+import { Controller } from "react-hook-form";
+import { ISideDrawerFieldProps } from "../types";
+
+import { useFieldStyles } from "components/SideDrawer/Form/utils";
+import { getDurationString } from "./utils";
+
+export default function Duration({ column, control }: ISideDrawerFieldProps) {
+ const fieldClasses = useFieldStyles();
+
+ return (
+ {
+ if (
+ !value ||
+ !value.start ||
+ !("toDate" in value.start) ||
+ !value.end ||
+ !("toDate" in value.end)
+ )
+ return
;
+
+ return (
+
+ {getDurationString(value.start.toDate(), value.end.toDate())}
+
+ );
+ }}
+ />
+ );
+}
diff --git a/src/components/fields/Duration/TableCell.tsx b/src/components/fields/Duration/TableCell.tsx
new file mode 100644
index 000000000..9d993f894
--- /dev/null
+++ b/src/components/fields/Duration/TableCell.tsx
@@ -0,0 +1,16 @@
+import { IHeavyCellProps } from "../types";
+
+import { getDurationString } from "./utils";
+
+export default function Duration({ value }: IHeavyCellProps) {
+ if (
+ !value ||
+ !value.start ||
+ !("toDate" in value.start) ||
+ !value.end ||
+ !("toDate" in value.end)
+ )
+ return null;
+
+ return <>{getDurationString(value.start.toDate(), value.end.toDate())}>;
+}
diff --git a/src/components/fields/Duration/index.tsx b/src/components/fields/Duration/index.tsx
new file mode 100644
index 000000000..28821700b
--- /dev/null
+++ b/src/components/fields/Duration/index.tsx
@@ -0,0 +1,31 @@
+import { lazy } from "react";
+import { IFieldConfig, FieldType } from "components/fields/types";
+import withHeavyCell from "../_withTableCell/withHeavyCell";
+
+import DurationIcon from "@material-ui/icons/Timer";
+import BasicCell from "../_BasicCell/BasicCellNull";
+import NullEditor from "components/Table/editors/NullEditor";
+
+const TableCell = lazy(
+ () => import("./TableCell" /* webpackChunkName: "TableCell-Duration" */)
+);
+const SideDrawerField = lazy(
+ () =>
+ import(
+ "./SideDrawerField" /* webpackChunkName: "SideDrawerField-Duration" */
+ )
+);
+
+export const config: IFieldConfig = {
+ type: FieldType.duration,
+ name: "Duration",
+ dataType:
+ "{ start: firebase.firestore.Timestamp, end?: firebase.firestore.Timestamp }",
+ initialValue: {},
+ icon: ,
+ description: "Duration calculated from two timestamps.",
+ TableCell: withHeavyCell(BasicCell, TableCell),
+ TableEditor: NullEditor as any,
+ SideDrawerField,
+};
+export default config;
diff --git a/src/components/fields/Duration/utils.ts b/src/components/fields/Duration/utils.ts
new file mode 100644
index 000000000..3acb860d2
--- /dev/null
+++ b/src/components/fields/Duration/utils.ts
@@ -0,0 +1,12 @@
+export const getDurationString = (start: Date, end: Date) => {
+ let distance = Math.abs(end.getTime() - start.getTime());
+ const hours = Math.floor(distance / 3600000);
+ distance -= hours * 3600000;
+ const minutes = Math.floor(distance / 60000);
+ distance -= minutes * 60000;
+ const seconds = Math.floor(distance / 1000);
+
+ return `${hours ? `${hours}h` : ""} ${("0" + minutes).slice(-2)}m ${(
+ "0" + seconds
+ ).slice(-2)}s`;
+};
diff --git a/src/components/fields/Email/SideDrawerField.tsx b/src/components/fields/Email/SideDrawerField.tsx
new file mode 100644
index 000000000..3336001cb
--- /dev/null
+++ b/src/components/fields/Email/SideDrawerField.tsx
@@ -0,0 +1,38 @@
+import { Controller } from "react-hook-form";
+import { ISideDrawerFieldProps } from "../types";
+
+import { TextField } from "@material-ui/core";
+
+export default function Email({
+ control,
+ column,
+ disabled,
+}: ISideDrawerFieldProps) {
+ return (
+ {
+ return (
+
+ );
+ }}
+ />
+ );
+}
diff --git a/www/src/components/fields/Email/index.tsx b/src/components/fields/Email/index.tsx
similarity index 53%
rename from www/src/components/fields/Email/index.tsx
rename to src/components/fields/Email/index.tsx
index 25b8f8c1a..7c09130b4 100644
--- a/www/src/components/fields/Email/index.tsx
+++ b/src/components/fields/Email/index.tsx
@@ -7,20 +7,20 @@ import BasicCell from "../_BasicCell/BasicCellValue";
import TextEditor from "components/Table/editors/TextEditor";
const SideDrawerField = lazy(
- () =>
- import("./SideDrawerField" /* webpackChunkName: "SideDrawerField-Email" */)
+ () =>
+ import("./SideDrawerField" /* webpackChunkName: "SideDrawerField-Email" */)
);
export const config: IFieldConfig = {
- type: FieldType.email,
- name: "Email",
- dataType: "string",
- initialValue: "",
- initializable: true,
- icon: ,
- description: "Email address. Firetable does not validate emails.",
- TableCell: withBasicCell(BasicCell),
- TableEditor: TextEditor,
- SideDrawerField,
+ type: FieldType.email,
+ name: "Email",
+ dataType: "string",
+ initialValue: "",
+ initializable: true,
+ icon: ,
+ description: "Email address. Rowy does not validate emails.",
+ TableCell: withBasicCell(BasicCell),
+ TableEditor: TextEditor,
+ SideDrawerField,
};
export default config;
diff --git a/src/components/fields/File/SideDrawerField.tsx b/src/components/fields/File/SideDrawerField.tsx
new file mode 100644
index 000000000..7737a6c6e
--- /dev/null
+++ b/src/components/fields/File/SideDrawerField.tsx
@@ -0,0 +1,192 @@
+import { useCallback, useState } from "react";
+import { ISideDrawerFieldProps } from "../types";
+import clsx from "clsx";
+import { Controller } from "react-hook-form";
+import { format } from "date-fns";
+
+import { useDropzone } from "react-dropzone";
+import useUploader, { FileValue } from "hooks/useRowy/useUploader";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import {
+ alpha,
+ ButtonBase,
+ Typography,
+ Grid,
+ Tooltip,
+ Chip,
+ CircularProgress,
+} from "@material-ui/core";
+import UploadIcon from "assets/icons/Upload";
+import { FileIcon } from ".";
+
+import Confirmation from "components/Confirmation";
+import { DATE_TIME_FORMAT } from "constants/dates";
+
+import { useFieldStyles } from "components/SideDrawer/Form/utils";
+import { useRowyContext } from "contexts/RowyContext";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ dropzoneButton: {
+ justifyContent: "flex-start",
+ color: theme.palette.text.secondary,
+ "& svg": { marginRight: theme.spacing(2) },
+ },
+ dropzoneDragActive: {
+ backgroundColor: alpha(
+ theme.palette.primary.light,
+ theme.palette.action.hoverOpacity * 2
+ ),
+ color: theme.palette.primary.main,
+ },
+
+ chipList: { marginTop: theme.spacing(1) },
+ chipGridItem: { maxWidth: "100%" },
+ chip: { width: "100%" },
+ })
+);
+
+function ControlledFileUploader({
+ onChange,
+
+ value,
+ column,
+ docRef,
+ disabled,
+}) {
+ const classes = useStyles();
+ const fieldClasses = useFieldStyles();
+ const { updateCell } = useRowyContext();
+
+ const { uploaderState, upload, deleteUpload } = useUploader();
+ const {} = uploaderState;
+
+ // Store a preview image locally while uploading
+ const [localFile, setLocalFile] = useState("");
+
+ const onDrop = useCallback(
+ (acceptedFiles: File[]) => {
+ const file = acceptedFiles[0];
+
+ if (docRef && file) {
+ upload({
+ docRef,
+ fieldName: column.key,
+ files: [file],
+ previousValue: value ?? [],
+ onComplete: (newValue) => {
+ if (updateCell) updateCell(docRef, column.key, newValue);
+ onChange(newValue);
+ setLocalFile("");
+ },
+ });
+ setLocalFile(file.name);
+ }
+ },
+ [docRef, value]
+ );
+
+ const handleDelete = (index: number) => {
+ const newValue = [...value];
+ const toBeDeleted = newValue.splice(index, 1);
+ toBeDeleted.length && deleteUpload(toBeDeleted[0]);
+ onChange(newValue);
+ };
+
+ const { getRootProps, getInputProps, isDragActive } = useDropzone({
+ onDrop,
+ multiple: false,
+ });
+
+ return (
+ <>
+ {!disabled && (
+
+
+
+
+ Upload file
+
+
+ )}
+
+
+ {Array.isArray(value) &&
+ value.map((file: FileValue, i) => (
+
+
+
+
+ }
+ label={file.name}
+ onClick={() => window.open(file.downloadURL)}
+ onDelete={!disabled ? () => handleDelete(i) : undefined}
+ className={classes.chip}
+ />
+
+
+
+
+ ))}
+
+ {localFile && (
+
+ }
+ label={localFile}
+ className={classes.chip}
+ //onDelete={() => {}}
+ deleteIcon={
+
+ }
+ />
+
+ )}
+
+ >
+ );
+}
+
+export default function File_({
+ control,
+ column,
+ disabled,
+ docRef,
+}: ISideDrawerFieldProps) {
+ return (
+ (
+
+ )}
+ />
+ );
+}
diff --git a/src/components/fields/File/TableCell.tsx b/src/components/fields/File/TableCell.tsx
new file mode 100644
index 000000000..c5dcfec7e
--- /dev/null
+++ b/src/components/fields/File/TableCell.tsx
@@ -0,0 +1,185 @@
+import { useCallback } from "react";
+import { IHeavyCellProps } from "../types";
+
+import { useDropzone } from "react-dropzone";
+import _findIndex from "lodash/findIndex";
+import clsx from "clsx";
+import { format } from "date-fns";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import {
+ alpha,
+ Grid,
+ Tooltip,
+ Chip,
+ IconButton,
+ CircularProgress,
+} from "@material-ui/core";
+import UploadIcon from "assets/icons/Upload";
+
+import { useConfirmation } from "components/ConfirmationDialog";
+import useUploader, { FileValue } from "hooks/useRowy/useUploader";
+import { FileIcon } from ".";
+import { DATE_TIME_FORMAT } from "constants/dates";
+import { useRowyContext } from "contexts/RowyContext";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: {
+ padding: theme.spacing(0, 0.75, 0, 1),
+ outline: "none",
+ },
+ dragActive: {
+ backgroundColor: alpha(
+ theme.palette.primary.main,
+ theme.palette.action.hoverOpacity * 2
+ ),
+
+ "& .row-hover-iconButton": { color: theme.palette.primary.main },
+ },
+
+ chipList: { overflow: "hidden" },
+ chipGridItem: {
+ // Truncate so multiple files still visible
+ maxWidth: `calc(100% - ${theme.spacing(3.5)})`,
+ },
+ chip: { width: "100%" },
+
+ endButtonContainer: {
+ width: 29 + theme.spacing(1),
+ },
+ circularProgress: {
+ display: "block",
+ margin: "0 auto",
+ },
+ })
+);
+
+export default function File_({
+ column,
+ row,
+ value,
+ onSubmit,
+ disabled,
+}: IHeavyCellProps) {
+ const classes = useStyles();
+ const { updateCell } = useRowyContext();
+
+ const { uploaderState, upload, deleteUpload } = useUploader();
+ const { progress, isLoading } = uploaderState;
+ const { requestConfirmation } = useConfirmation();
+ const onDrop = useCallback(
+ (acceptedFiles) => {
+ const file = acceptedFiles[0];
+
+ if (file) {
+ upload({
+ docRef: row.ref,
+ fieldName: column.key as string,
+ files: [file],
+ previousValue: value,
+ onComplete: (newValue) => {
+ if (updateCell) updateCell(row.ref, column.key, newValue);
+ },
+ });
+ }
+ },
+ [value]
+ );
+
+ const handleDelete = (ref: string) => {
+ const newValue = [...value];
+ const index = _findIndex(newValue, ["ref", ref]);
+ const toBeDeleted = newValue.splice(index, 1);
+ toBeDeleted.length && deleteUpload(toBeDeleted[0]);
+ onSubmit(newValue);
+ };
+
+ const { getRootProps, getInputProps, isDragActive } = useDropzone({
+ onDrop,
+ multiple: false,
+ });
+
+ const dropzoneProps = getRootProps();
+
+ return (
+
+
+
+
+
+ {Array.isArray(value) &&
+ value.reverse().map((file: FileValue) => (
+
+
+ }
+ label={file.name}
+ onClick={(e) => {
+ window.open(file.downloadURL);
+ e.stopPropagation();
+ }}
+ onDelete={
+ disabled
+ ? undefined
+ : () =>
+ requestConfirmation({
+ handleConfirm: () => handleDelete(file.ref),
+ title: "Delete File",
+ body:
+ "Are you sure you want to delete this file?",
+ confirm: "Delete",
+ })
+ }
+ className={classes.chip}
+ />
+
+
+ ))}
+
+
+
+
+ {!isLoading ? (
+ !disabled && (
+ {
+ dropzoneProps.onClick!(e);
+ e.stopPropagation();
+ }}
+ >
+
+
+ )
+ ) : (
+
+ )}
+
+
+ );
+}
diff --git a/src/components/fields/File/index.tsx b/src/components/fields/File/index.tsx
new file mode 100644
index 000000000..86270df14
--- /dev/null
+++ b/src/components/fields/File/index.tsx
@@ -0,0 +1,31 @@
+import { lazy } from "react";
+import { IFieldConfig, FieldType } from "components/fields/types";
+import withHeavyCell from "../_withTableCell/withHeavyCell";
+
+import FileIcon from "@material-ui/icons/AttachFile";
+import BasicCell from "../_BasicCell/BasicCellNull";
+import NullEditor from "components/Table/editors/NullEditor";
+
+const TableCell = lazy(
+ () => import("./TableCell" /* webpackChunkName: "TableCell-File" */)
+);
+const SideDrawerField = lazy(
+ () =>
+ import("./SideDrawerField" /* webpackChunkName: "SideDrawerField-File" */)
+);
+
+export const config: IFieldConfig = {
+ type: FieldType.file,
+ name: "File",
+ dataType:
+ "{ downloadURL: string, lastModifiedTS: number, name: string, type, ref }[]",
+ initialValue: [],
+ icon: ,
+ description: "File uploaded to Firebase Storage. Supports any file type.",
+ TableCell: withHeavyCell(BasicCell, TableCell),
+ TableEditor: NullEditor as any,
+ SideDrawerField,
+};
+export default config;
+
+export { FileIcon };
diff --git a/src/components/fields/Id/SideDrawerField.tsx b/src/components/fields/Id/SideDrawerField.tsx
new file mode 100644
index 000000000..efcc0b6d7
--- /dev/null
+++ b/src/components/fields/Id/SideDrawerField.tsx
@@ -0,0 +1,18 @@
+import { ISideDrawerFieldProps } from "../types";
+
+import { useTheme } from "@material-ui/core";
+import { useFieldStyles } from "components/SideDrawer/Form/utils";
+
+export default function Id({ docRef }: ISideDrawerFieldProps) {
+ const theme = useTheme();
+ const fieldClasses = useFieldStyles();
+
+ return (
+
+ {docRef.id}
+
+ );
+}
diff --git a/src/components/fields/Id/TableCell.tsx b/src/components/fields/Id/TableCell.tsx
new file mode 100644
index 000000000..5e220b2bd
--- /dev/null
+++ b/src/components/fields/Id/TableCell.tsx
@@ -0,0 +1,15 @@
+import { IHeavyCellProps } from "../types";
+
+import { useTheme } from "@material-ui/core";
+
+export default function Id({ docRef }: IHeavyCellProps) {
+ const theme = useTheme();
+
+ return (
+
+ {docRef.id}
+
+ );
+}
diff --git a/www/src/components/fields/Id/index.tsx b/src/components/fields/Id/index.tsx
similarity index 51%
rename from www/src/components/fields/Id/index.tsx
rename to src/components/fields/Id/index.tsx
index 2ca5c7766..071ad54a7 100644
--- a/www/src/components/fields/Id/index.tsx
+++ b/src/components/fields/Id/index.tsx
@@ -7,21 +7,21 @@ import BasicCell from "../_BasicCell/BasicCellValue";
import withSideDrawerEditor from "components/Table/editors/withSideDrawerEditor";
const TableCell = lazy(
- () => import("./TableCell" /* webpackChunkName: "TableCell-Id" */)
+ () => import("./TableCell" /* webpackChunkName: "TableCell-Id" */)
);
const SideDrawerField = lazy(
- () => import("./SideDrawerField" /* webpackChunkName: "SideDrawerField-Id" */)
+ () => import("./SideDrawerField" /* webpackChunkName: "SideDrawerField-Id" */)
);
export const config: IFieldConfig = {
- type: FieldType.id,
- name: "ID",
- dataType: "undefined",
- initialValue: "",
- icon: ,
- description: "Displays the row’s document ID. Cannot be sorted.",
- TableCell: withHeavyCell(BasicCell, TableCell),
- TableEditor: withSideDrawerEditor(TableCell),
- SideDrawerField,
+ type: FieldType.id,
+ name: "ID",
+ dataType: "undefined",
+ initialValue: "",
+ icon: ,
+ description: "Displays the row’s document ID. Cannot be sorted.",
+ TableCell: withHeavyCell(BasicCell, TableCell),
+ TableEditor: withSideDrawerEditor(TableCell),
+ SideDrawerField,
};
export default config;
diff --git a/src/components/fields/Image/SideDrawerField.tsx b/src/components/fields/Image/SideDrawerField.tsx
new file mode 100644
index 000000000..bc6f5432d
--- /dev/null
+++ b/src/components/fields/Image/SideDrawerField.tsx
@@ -0,0 +1,286 @@
+import { ISideDrawerFieldProps } from "../types";
+import { useCallback, useState } from "react";
+import clsx from "clsx";
+import { Controller } from "react-hook-form";
+
+import { useDropzone } from "react-dropzone";
+import useUploader from "hooks/useRowy/useUploader";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import {
+ alpha,
+ ButtonBase,
+ Typography,
+ Grid,
+ CircularProgress,
+ Tooltip,
+} from "@material-ui/core";
+
+import AddIcon from "@material-ui/icons/AddAPhoto";
+import DeleteIcon from "@material-ui/icons/Delete";
+import OpenIcon from "@material-ui/icons/OpenInNewOutlined";
+
+import { IMAGE_MIME_TYPES } from ".";
+import Thumbnail from "components/Thumbnail";
+import { useConfirmation } from "components/ConfirmationDialog";
+import { useRowyContext } from "contexts/RowyContext";
+
+import { useFieldStyles } from "components/SideDrawer/Form/utils";
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ dropzoneButton: {
+ justifyContent: "flex-start",
+ color: theme.palette.text.secondary,
+ "& svg": { marginRight: theme.spacing(2) },
+ },
+ dropzoneDragActive: {
+ backgroundColor: alpha(
+ theme.palette.primary.light,
+ theme.palette.action.hoverOpacity * 2
+ ),
+ color: theme.palette.primary.main,
+ },
+
+ imagesContainer: {
+ marginTop: theme.spacing(1),
+ },
+
+ img: {
+ position: "relative",
+ width: 80,
+ height: 80,
+ borderRadius: theme.shape.borderRadius,
+ // boxShadow: `0 0 0 1px ${theme.palette.divider} inset`,
+
+ backgroundSize: "contain",
+ backgroundPosition: "center center",
+ backgroundRepeat: "no-repeat",
+ },
+ thumbnail: {
+ position: "absolute",
+ top: 0,
+ left: 0,
+ width: "100%",
+ height: "100%",
+ },
+
+ overlay: {
+ position: "absolute",
+ top: 0,
+ left: 0,
+ bottom: 0,
+ right: 0,
+
+ backgroundColor: alpha(theme.palette.background.paper, 0.8),
+ color: theme.palette.text.secondary,
+ boxShadow: `0 0 0 1px ${theme.palette.divider} inset`,
+ borderRadius: theme.shape.borderRadius,
+ },
+
+ deleteImgHover: {
+ transition: theme.transitions.create("background-color", {
+ duration: theme.transitions.duration.shortest,
+ }),
+
+ backgroundColor: "transparent",
+
+ "$img:hover &": {
+ backgroundColor: alpha(theme.palette.background.paper, 0.8),
+ "& *": { opacity: 1 },
+ },
+
+ "& *": {
+ opacity: 0,
+ transition: theme.transitions.create("opacity", {
+ duration: theme.transitions.duration.shortest,
+ }),
+ },
+ },
+ })
+);
+
+function ControlledImageUploader({
+ onChange,
+ value,
+ column,
+ docRef,
+ disabled,
+}) {
+ const classes = useStyles();
+ const fieldClasses = useFieldStyles();
+ const { updateCell } = useRowyContext();
+
+ const { requestConfirmation } = useConfirmation();
+ const { uploaderState, upload, deleteUpload } = useUploader();
+ const { progress } = uploaderState;
+
+ // Store a preview image locally while uploading
+ const [localImage, setLocalImage] = useState("");
+
+ const onDrop = useCallback(
+ (acceptedFiles) => {
+ const imageFile = acceptedFiles[0];
+
+ if (docRef && imageFile) {
+ upload({
+ docRef,
+ fieldName: column.key,
+ files: [imageFile],
+ previousValue: value ?? [],
+ onComplete: (newValue) => {
+ if (updateCell) updateCell(docRef, column.key, newValue);
+ onChange(newValue);
+ setLocalImage("");
+ },
+ });
+ setLocalImage(URL.createObjectURL(imageFile));
+ }
+ },
+ [docRef, value]
+ );
+
+ const handleDelete = (index: number) => {
+ const newValue = [...value];
+ const toBeDeleted = newValue.splice(index, 1);
+ toBeDeleted.length && deleteUpload(toBeDeleted[0]);
+ onChange(newValue);
+ };
+
+ const { getRootProps, getInputProps, isDragActive } = useDropzone({
+ onDrop,
+ multiple: false,
+ accept: IMAGE_MIME_TYPES,
+ });
+
+ return (
+ <>
+ {!disabled && (
+
+
+
+
+ {isDragActive ? "Drop your image here" : "Upload image"}
+
+
+ )}
+
+
+ {Array.isArray(value) &&
+ value.map((image, i) => (
+
+ {disabled ? (
+
+ window.open(image.downloadURL, "_blank")}
+ >
+
+
+ {disabled ? : }
+
+
+
+ ) : (
+
+
+
+ requestConfirmation({
+ title: "Delete Image",
+ body: "Are you sure you want to delete this image?",
+ confirm: "Delete",
+ handleConfirm: () => handleDelete(i),
+ })
+ }
+ >
+
+
+
+
+
+
+
+ )}
+
+ ))}
+
+ {localImage && (
+
+
+
+
+
+
+
+ )}
+
+ >
+ );
+}
+
+export default function Image_({
+ control,
+ column,
+ disabled,
+ docRef,
+}: ISideDrawerFieldProps) {
+ return (
+ (
+
+ )}
+ />
+ );
+}
diff --git a/src/components/fields/Image/TableCell.tsx b/src/components/fields/Image/TableCell.tsx
new file mode 100644
index 000000000..eab9e9224
--- /dev/null
+++ b/src/components/fields/Image/TableCell.tsx
@@ -0,0 +1,290 @@
+import { IHeavyCellProps } from "../types";
+import { useCallback, useState } from "react";
+
+import { useDropzone } from "react-dropzone";
+import _findIndex from "lodash/findIndex";
+import clsx from "clsx";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import {
+ alpha,
+ Grid,
+ IconButton,
+ ButtonBase,
+ CircularProgress,
+ Tooltip,
+} from "@material-ui/core";
+import AddIcon from "@material-ui/icons/AddAPhoto";
+import DeleteIcon from "@material-ui/icons/Delete";
+import OpenIcon from "@material-ui/icons/OpenInNewOutlined";
+
+import { useConfirmation } from "components/ConfirmationDialog";
+import useUploader, { FileValue } from "hooks/useRowy/useUploader";
+import { IMAGE_MIME_TYPES } from "./index";
+import { useRowyContext } from "contexts/RowyContext";
+import Thumbnail from "components/Thumbnail";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: {
+ padding: theme.spacing(0, 0.875, 0, 1.125),
+ outline: "none",
+ },
+ dragActive: {
+ backgroundColor: alpha(
+ theme.palette.primary.main,
+ theme.palette.action.hoverOpacity * 2
+ ),
+
+ "& .row-hover-iconButton": { color: theme.palette.primary.main },
+ },
+
+ imglistContainer: {
+ maxWidth: `calc(100% - 30px)`,
+ overflowX: "hidden",
+ },
+
+ img: ({ rowHeight }: { rowHeight: number }) => ({
+ position: "relative",
+ display: "flex",
+
+ width: `calc(${rowHeight}px - ${theme.spacing(1)} - 1)`,
+ height: `calc(${rowHeight}px - ${theme.spacing(1)} - 1)`,
+
+ backgroundSize: "contain",
+ backgroundPosition: "center center",
+ backgroundRepeat: "no-repeat",
+
+ borderRadius: theme.shape.borderRadius,
+ }),
+ thumbnail: {
+ position: "absolute",
+ top: 0,
+ left: 0,
+ width: "100%",
+ height: "100%",
+ },
+
+ deleteImgHover: {
+ position: "absolute",
+ top: 0,
+ left: 0,
+ bottom: 0,
+ right: 0,
+
+ color: theme.palette.text.secondary,
+ boxShadow: `0 0 0 1px ${theme.palette.divider} inset`,
+ borderRadius: theme.shape.borderRadius,
+
+ transition: theme.transitions.create("background-color", {
+ duration: theme.transitions.duration.shortest,
+ }),
+
+ "& *": {
+ opacity: 0,
+ transition: theme.transitions.create("opacity", {
+ duration: theme.transitions.duration.shortest,
+ }),
+ },
+
+ "$img:hover &": {
+ backgroundColor: alpha(theme.palette.background.paper, 0.8),
+ "& *": { opacity: 1 },
+ },
+ },
+
+ localImgPreview: {
+ boxShadow: `0 0 0 1px ${theme.palette.divider} inset`,
+ },
+
+ endButtonContainer: {
+ width: 29 + theme.spacing(1),
+ },
+ circularProgress: {
+ display: "block",
+ margin: "0 auto",
+ },
+ })
+);
+
+export default function Image_({
+ column,
+ row,
+ value,
+ onSubmit,
+ disabled,
+}: IHeavyCellProps) {
+ const { tableState, updateCell } = useRowyContext();
+ const { requestConfirmation } = useConfirmation();
+ const classes = useStyles({ rowHeight: tableState?.config?.rowHeight ?? 44 });
+
+ const { uploaderState, upload, deleteUpload } = useUploader();
+ const { progress, isLoading } = uploaderState;
+
+ // Store a preview image locally while uploading
+ const [localImage, setLocalImage] = useState("");
+
+ const onDrop = useCallback(
+ (acceptedFiles) => {
+ const imageFile = acceptedFiles[0];
+
+ if (imageFile) {
+ upload({
+ docRef: row.ref,
+ fieldName: column.key as string,
+ files: [imageFile],
+ previousValue: value,
+ onComplete: (newValue) => {
+ if (updateCell) updateCell(row.ref, column.key, newValue);
+ setLocalImage("");
+ },
+ });
+ setLocalImage(URL.createObjectURL(imageFile));
+ }
+ },
+ [value]
+ );
+
+ const handleDelete = (ref: string) => () => {
+ const newValue = [...value];
+ const index = _findIndex(newValue, ["ref", ref]);
+ const toBeDeleted = newValue.splice(index, 1);
+ toBeDeleted.length && deleteUpload(toBeDeleted[0]);
+ onSubmit(newValue);
+ };
+
+ const { getRootProps, getInputProps, isDragActive } = useDropzone({
+ onDrop,
+ multiple: false,
+ accept: IMAGE_MIME_TYPES,
+ });
+
+ const dropzoneProps = getRootProps();
+
+ let thumbnailSize = "100x100";
+ if (tableState?.config?.rowHeight) {
+ if (tableState!.config!.rowHeight! > 50) thumbnailSize = "200x200";
+ if (tableState!.config!.rowHeight! > 100) thumbnailSize = "400x400";
+ }
+
+ return (
+
+
+
+
+
+ {Array.isArray(value) &&
+ value.map((file: FileValue) => (
+
+ {disabled ? (
+
+ window.open(file.downloadURL, "_blank")}
+ >
+
+
+ {disabled ? (
+
+ ) : (
+
+ )}
+
+
+
+ ) : (
+
+
+ {
+ requestConfirmation({
+ title: "Delete Image",
+ body: "Are you sure you want to delete this image?",
+ confirm: "Delete",
+ handleConfirm: handleDelete(file.ref),
+ });
+ }}
+ >
+
+
+
+
+
+
+
+ )}
+
+ ))}
+
+ {localImage && (
+
+
+
+ )}
+
+
+
+
+ {!isLoading ? (
+ !disabled && (
+ {
+ dropzoneProps.onClick!(e);
+ e.stopPropagation();
+ }}
+ color="inherit"
+ >
+
+
+ )
+ ) : (
+
+ )}
+
+
+ );
+}
diff --git a/src/components/fields/Image/index.tsx b/src/components/fields/Image/index.tsx
new file mode 100644
index 000000000..c09454f2b
--- /dev/null
+++ b/src/components/fields/Image/index.tsx
@@ -0,0 +1,38 @@
+import { lazy } from "react";
+import { IFieldConfig, FieldType } from "components/fields/types";
+import withHeavyCell from "../_withTableCell/withHeavyCell";
+
+import ImageIcon from "assets/icons/Image";
+import BasicCell from "../_BasicCell/BasicCellNull";
+import NullEditor from "components/Table/editors/NullEditor";
+
+const TableCell = lazy(
+ () => import("./TableCell" /* webpackChunkName: "TableCell-Image" */)
+);
+const SideDrawerField = lazy(
+ () =>
+ import("./SideDrawerField" /* webpackChunkName: "SideDrawerField-Image" */)
+);
+
+export const config: IFieldConfig = {
+ type: FieldType.image,
+ name: "Image",
+ dataType:
+ "{ downloadURL: string, lastModifiedTS: number, name: string, type, ref }[]",
+ initialValue: [],
+ icon: ,
+ description:
+ "Image file uploaded to Firebase Storage. Supports JPEG, PNG, SVG, GIF, WebP.",
+ TableCell: withHeavyCell(BasicCell, TableCell),
+ TableEditor: NullEditor as any,
+ SideDrawerField,
+};
+export default config;
+
+export const IMAGE_MIME_TYPES = [
+ "image/jpeg",
+ "image/png",
+ "image/svg+xml",
+ "image/gif",
+ "image/webp",
+];
diff --git a/src/components/fields/Json/BasicCell.tsx b/src/components/fields/Json/BasicCell.tsx
new file mode 100644
index 000000000..7176ae0b0
--- /dev/null
+++ b/src/components/fields/Json/BasicCell.tsx
@@ -0,0 +1,33 @@
+import jsonFormat from "json-format";
+import { IBasicCellProps } from "../types";
+
+import { useTheme } from "@material-ui/core";
+
+export default function Json({ value }: IBasicCellProps) {
+ const theme = useTheme();
+
+ if (!value) return null;
+
+ const formattedJson = jsonFormat(value, {
+ type: "space",
+ char: " ",
+ size: 2,
+ });
+
+ return (
+
+ {formattedJson}
+
+ );
+}
diff --git a/src/components/fields/Json/Settings.tsx b/src/components/fields/Json/Settings.tsx
new file mode 100644
index 000000000..ccad15cf7
--- /dev/null
+++ b/src/components/fields/Json/Settings.tsx
@@ -0,0 +1,19 @@
+import { Switch, FormControlLabel } from "@material-ui/core";
+
+const Settings = ({ config, handleChange }) => {
+ return (
+ <>
+ handleChange("isArray")(!Boolean(config.isArray))}
+ name="isArray"
+ />
+ }
+ label="Set as an array"
+ />
+ >
+ );
+};
+export default Settings;
diff --git a/src/components/fields/Json/SideDrawerField.tsx b/src/components/fields/Json/SideDrawerField.tsx
new file mode 100644
index 000000000..1d1e3cc96
--- /dev/null
+++ b/src/components/fields/Json/SideDrawerField.tsx
@@ -0,0 +1,111 @@
+import clsx from "clsx";
+import { Controller } from "react-hook-form";
+import { ISideDrawerFieldProps } from "../types";
+
+import ReactJson from "react-json-view";
+import jsonFormat from "json-format";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { useTheme } from "@material-ui/core";
+import { useFieldStyles } from "components/SideDrawer/Form/utils";
+
+const isValidJson = (val: any) => {
+ try {
+ if (typeof val === "string") JSON.parse(val);
+ else JSON.stringify(val);
+ } catch (error) {
+ return false;
+ }
+ return true;
+};
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: {
+ padding: theme.spacing(2),
+ margin: 0,
+ overflowX: "auto",
+ ...theme.typography.caption,
+ },
+
+ readOnly: {
+ whiteSpace: "pre-wrap",
+ ...theme.typography.caption,
+ fontFamily: theme.typography.fontFamilyMono,
+ wordBreak: "break-word",
+ },
+ })
+);
+
+export default function Json({
+ control,
+ column,
+ disabled,
+}: ISideDrawerFieldProps) {
+ const fieldClasses = useFieldStyles();
+ const classes = useStyles();
+ const theme = useTheme();
+ return (
+ {
+ if (disabled)
+ return (
+
+ {value &&
+ jsonFormat(value, {
+ type: "space",
+ char: " ",
+ size: 2,
+ })}
+
+ );
+
+ const handleEdit = (edit) => {
+ onChange(edit.updated_src);
+ };
+
+ return (
+
+
+
+ );
+ }}
+ />
+ );
+}
diff --git a/src/components/fields/Json/index.tsx b/src/components/fields/Json/index.tsx
new file mode 100644
index 000000000..9c8d2e581
--- /dev/null
+++ b/src/components/fields/Json/index.tsx
@@ -0,0 +1,38 @@
+import { lazy } from "react";
+import { IFieldConfig, FieldType } from "components/fields/types";
+import withBasicCell from "../_withTableCell/withBasicCell";
+
+import JsonIcon from "assets/icons/Json";
+import BasicCell from "./BasicCell";
+import withSideDrawerEditor from "components/Table/editors/withSideDrawerEditor";
+
+const SideDrawerField = lazy(
+ () =>
+ import("./SideDrawerField" /* webpackChunkName: "SideDrawerField-Json" */)
+);
+
+const Settings = lazy(
+ () => import("./Settings" /* webpackChunkName: "Settings-Json" */)
+);
+
+export const config: IFieldConfig = {
+ type: FieldType.json,
+ name: "JSON",
+ dataType: "any",
+ initialValue: {},
+ initializable: true,
+ icon: ,
+ description: "JSON object editable with a visual JSON editor.",
+ TableCell: withBasicCell(BasicCell),
+ TableEditor: withSideDrawerEditor(BasicCell),
+ csvImportParser: (value) => {
+ try {
+ return JSON.parse(value);
+ } catch (e) {
+ return null;
+ }
+ },
+ SideDrawerField,
+ settings: Settings,
+};
+export default config;
diff --git a/src/components/fields/LongText/BasicCell.tsx b/src/components/fields/LongText/BasicCell.tsx
new file mode 100644
index 000000000..3186fe0df
--- /dev/null
+++ b/src/components/fields/LongText/BasicCell.tsx
@@ -0,0 +1,22 @@
+import { IBasicCellProps } from "../types";
+
+import { useTheme } from "@material-ui/core";
+
+export default function LongText({ value }: IBasicCellProps) {
+ const theme = useTheme();
+
+ return (
+
+ {value}
+
+ );
+}
diff --git a/src/components/fields/LongText/SideDrawerField.tsx b/src/components/fields/LongText/SideDrawerField.tsx
new file mode 100644
index 000000000..3ebd4690e
--- /dev/null
+++ b/src/components/fields/LongText/SideDrawerField.tsx
@@ -0,0 +1,37 @@
+import { Controller } from "react-hook-form";
+import { ISideDrawerFieldProps } from "../types";
+
+import { TextField } from "@material-ui/core";
+
+export default function LongText({
+ control,
+ column,
+ disabled,
+}: ISideDrawerFieldProps) {
+ return (
+ {
+ return (
+
+ );
+ }}
+ />
+ );
+}
diff --git a/www/src/components/fields/LongText/index.tsx b/src/components/fields/LongText/index.tsx
similarity index 50%
rename from www/src/components/fields/LongText/index.tsx
rename to src/components/fields/LongText/index.tsx
index ac4f3b70a..5fc883a26 100644
--- a/www/src/components/fields/LongText/index.tsx
+++ b/src/components/fields/LongText/index.tsx
@@ -7,22 +7,22 @@ import BasicCell from "./BasicCell";
import withSideDrawerEditor from "components/Table/editors/withSideDrawerEditor";
const SideDrawerField = lazy(
- () =>
- import(
- "./SideDrawerField" /* webpackChunkName: "SideDrawerField-LongText" */
- )
+ () =>
+ import(
+ "./SideDrawerField" /* webpackChunkName: "SideDrawerField-LongText" */
+ )
);
export const config: IFieldConfig = {
- type: FieldType.longText,
- name: "Long Text",
- dataType: "string",
- initialValue: "",
- initializable: true,
- icon: ,
- description: "Large amount of text, such as sentences and paragraphs.",
- TableCell: withBasicCell(BasicCell),
- TableEditor: withSideDrawerEditor(BasicCell),
- SideDrawerField,
+ type: FieldType.longText,
+ name: "Long Text",
+ dataType: "string",
+ initialValue: "",
+ initializable: true,
+ icon: ,
+ description: "Large amount of text, such as sentences and paragraphs.",
+ TableCell: withBasicCell(BasicCell),
+ TableEditor: withSideDrawerEditor(BasicCell),
+ SideDrawerField,
};
export default config;
diff --git a/src/components/fields/MultiSelect/ConvertStringToArray.tsx b/src/components/fields/MultiSelect/ConvertStringToArray.tsx
new file mode 100644
index 000000000..e23c2e28b
--- /dev/null
+++ b/src/components/fields/MultiSelect/ConvertStringToArray.tsx
@@ -0,0 +1,25 @@
+import { Grid, Tooltip, Button } from "@material-ui/core";
+
+export const ConvertStringToArray = ({ value, onSubmit }) => (
+
+
+ {value}
+
+
+
+ onSubmit([value])}
+ style={{
+ display: "flex",
+ minWidth: 0,
+ marginRight: -12,
+ paddingLeft: 12,
+ paddingRight: 12,
+ }}
+ >
+ Fix
+
+
+
+
+);
diff --git a/src/components/fields/MultiSelect/InlineCell.tsx b/src/components/fields/MultiSelect/InlineCell.tsx
new file mode 100644
index 000000000..1bd882c07
--- /dev/null
+++ b/src/components/fields/MultiSelect/InlineCell.tsx
@@ -0,0 +1,90 @@
+import React from "react";
+import clsx from "clsx";
+import { IPopoverInlineCellProps } from "../types";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { ButtonBase, Grid } from "@material-ui/core";
+import ArrowDropDownIcon from "@material-ui/icons/ArrowDropDown";
+
+import { sanitiseValue } from "./utils";
+import FormattedChip from "components/FormattedChip";
+import { ConvertStringToArray } from "./ConvertStringToArray";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ root: {
+ height: "100%",
+ padding: theme.spacing(0, 1, 0, 1.5),
+
+ font: "inherit",
+ color: "inherit !important",
+ letterSpacing: "inherit",
+ textAlign: "inherit",
+ justifyContent: "flex-start",
+ },
+
+ value: {
+ flex: 1,
+ maxWidth: `calc(100% - 24px + 4px)`,
+ overflow: "hidden",
+ marginRight: 0,
+ },
+ chip: {
+ display: "flex",
+ cursor: "inherit",
+ },
+ chipLabel: { whiteSpace: "nowrap" },
+
+ icon: {
+ display: "block",
+ color: theme.palette.action.active,
+ },
+ disabled: {
+ color: theme.palette.action.disabled,
+ },
+ })
+);
+
+export const MultiSelect = React.forwardRef(function MultiSelect(
+ { value, showPopoverCell, disabled, onSubmit }: IPopoverInlineCellProps,
+ ref: React.Ref
+) {
+ const classes = useStyles();
+
+ if (typeof value === "string" && value !== "")
+ return ;
+
+ return (
+ showPopoverCell(true)}
+ ref={ref}
+ disabled={disabled}
+ >
+
+ {sanitiseValue(value).map(
+ (item) =>
+ typeof item === "string" && (
+
+
+
+ )
+ )}
+
+
+
+
+ );
+});
+export default MultiSelect;
diff --git a/src/components/fields/MultiSelect/PopoverCell.tsx b/src/components/fields/MultiSelect/PopoverCell.tsx
new file mode 100644
index 000000000..6c40dae53
--- /dev/null
+++ b/src/components/fields/MultiSelect/PopoverCell.tsx
@@ -0,0 +1,41 @@
+import { IPopoverCellProps } from "../types";
+
+import MultiSelect_ from "@antlerengineering/multiselect";
+
+import { sanitiseValue } from "./utils";
+
+export default function MultiSelect({
+ value,
+ onSubmit,
+ column,
+ parentRef,
+ showPopoverCell,
+ disabled,
+}: IPopoverCellProps) {
+ const config = column.config ?? {};
+
+ return (
+ showPopoverCell(false)}
+ />
+ );
+}
diff --git a/src/components/fields/MultiSelect/SideDrawerField.tsx b/src/components/fields/MultiSelect/SideDrawerField.tsx
new file mode 100644
index 000000000..cf45e7a26
--- /dev/null
+++ b/src/components/fields/MultiSelect/SideDrawerField.tsx
@@ -0,0 +1,74 @@
+import { Controller } from "react-hook-form";
+import { ISideDrawerFieldProps } from "../types";
+
+import { useTheme, Grid } from "@material-ui/core";
+import MultiSelect_ from "@antlerengineering/multiselect";
+import FormattedChip from "components/FormattedChip";
+
+import { sanitiseValue } from "./utils";
+import { ConvertStringToArray } from "./ConvertStringToArray";
+
+export default function MultiSelect({
+ column,
+ control,
+ disabled,
+}: ISideDrawerFieldProps) {
+ const theme = useTheme();
+
+ const config = column.config ?? {};
+
+ return (
+ {
+ const handleDelete = (index: number) => () => {
+ const newValues = [...value];
+ newValues.splice(index, 1);
+ onChange(newValues);
+ };
+
+ if (typeof value === "string" && value !== "")
+ return ;
+
+ return (
+ <>
+
+
+ {value && Array.isArray(value) && (
+
+ {value.map(
+ (item, i) =>
+ item?.length > 0 && (
+
+
+
+ )
+ )}
+
+ )}
+ >
+ );
+ }}
+ />
+ );
+}
diff --git a/src/components/fields/MultiSelect/index.tsx b/src/components/fields/MultiSelect/index.tsx
new file mode 100644
index 000000000..b7520e5c1
--- /dev/null
+++ b/src/components/fields/MultiSelect/index.tsx
@@ -0,0 +1,51 @@
+import { lazy } from "react";
+import { IFieldConfig, FieldType } from "components/fields/types";
+import withPopoverCell from "../_withTableCell/withPopoverCell";
+
+import MultiSelectIcon from "assets/icons/MultiSelect";
+import BasicCell from "../_BasicCell/BasicCellNull";
+import InlineCell from "./InlineCell";
+import NullEditor from "components/Table/editors/NullEditor";
+
+const PopoverCell = lazy(
+ () =>
+ import("./PopoverCell" /* webpackChunkName: "PopoverCell-MultiSelect" */)
+);
+const SideDrawerField = lazy(
+ () =>
+ import(
+ "./SideDrawerField" /* webpackChunkName: "SideDrawerField-MultiSelect" */
+ )
+);
+const Settings = lazy(
+ () =>
+ import(
+ "../SingleSelect/Settings" /* webpackChunkName: "Settings-SingleSelect" */
+ )
+);
+
+export const config: IFieldConfig = {
+ type: FieldType.multiSelect,
+ name: "Multi Select",
+ dataType: "string[]",
+ initialValue: [],
+ initializable: true,
+ icon: ,
+ description:
+ "Dropdown selector with searchable options and check box behavior. Optionally allows users to input custom values. Max selection: all options.",
+ TableCell: withPopoverCell(BasicCell, InlineCell, PopoverCell, {
+ anchorOrigin: { horizontal: "left", vertical: "bottom" },
+ transparent: true,
+ }),
+ TableEditor: NullEditor as any,
+ SideDrawerField,
+ settings: Settings,
+ csvImportParser: (v) => {
+ if (v.includes(",")) {
+ return v.split(",").map((i) => i.trim());
+ } else if (v !== "") return [v];
+ else return v;
+ },
+ requireConfiguration: true,
+};
+export default config;
diff --git a/src/components/fields/MultiSelect/utils.ts b/src/components/fields/MultiSelect/utils.ts
new file mode 100644
index 000000000..265db5081
--- /dev/null
+++ b/src/components/fields/MultiSelect/utils.ts
@@ -0,0 +1,4 @@
+export const sanitiseValue = (value: any) => {
+ if (value === undefined || value === null || value === "") return [];
+ else return value as string[];
+};
diff --git a/www/src/components/fields/Number/BasicCell.tsx b/src/components/fields/Number/BasicCell.tsx
similarity index 76%
rename from www/src/components/fields/Number/BasicCell.tsx
rename to src/components/fields/Number/BasicCell.tsx
index 400b59a4f..bd91f39f9 100644
--- a/www/src/components/fields/Number/BasicCell.tsx
+++ b/src/components/fields/Number/BasicCell.tsx
@@ -1,5 +1,5 @@
import { IBasicCellProps } from "../types";
export default function Number_({ value }: IBasicCellProps) {
- return <>{`${value ?? ""}`}>;
+ return <>{`${value ?? ""}`}>;
}
diff --git a/src/components/fields/Number/SideDrawerField.tsx b/src/components/fields/Number/SideDrawerField.tsx
new file mode 100644
index 000000000..d83dbb408
--- /dev/null
+++ b/src/components/fields/Number/SideDrawerField.tsx
@@ -0,0 +1,37 @@
+import { Controller } from "react-hook-form";
+import { ISideDrawerFieldProps } from "../types";
+
+import { TextField } from "@material-ui/core";
+
+export default function Number_({
+ control,
+ column,
+ disabled,
+}: ISideDrawerFieldProps) {
+ return (
+ {
+ const handleChange = (e) => onChange(Number(e.target.value));
+
+ return (
+
+ );
+ }}
+ />
+ );
+}
diff --git a/src/components/fields/Number/index.tsx b/src/components/fields/Number/index.tsx
new file mode 100644
index 000000000..2c397fc83
--- /dev/null
+++ b/src/components/fields/Number/index.tsx
@@ -0,0 +1,34 @@
+import { lazy } from "react";
+import { IFieldConfig, FieldType } from "components/fields/types";
+import withBasicCell from "../_withTableCell/withBasicCell";
+
+import NumberIcon from "assets/icons/Number";
+import BasicCell from "./BasicCell";
+import TextEditor from "components/Table/editors/TextEditor";
+
+const SideDrawerField = lazy(
+ () =>
+ import("./SideDrawerField" /* webpackChunkName: "SideDrawerField-Number" */)
+);
+
+export const config: IFieldConfig = {
+ type: FieldType.number,
+ name: "Number",
+ dataType: "number",
+ initialValue: 0,
+ initializable: true,
+ icon: ,
+ description: "Numeric data.",
+ TableCell: withBasicCell(BasicCell),
+ TableEditor: TextEditor,
+ SideDrawerField,
+ csvImportParser: (v) => {
+ try {
+ const parsedValue = parseFloat(v);
+ return Number.isNaN(parsedValue) ? null : parsedValue;
+ } catch (e) {
+ return null;
+ }
+ },
+};
+export default config;
diff --git a/src/components/fields/Percentage/BasicCell.tsx b/src/components/fields/Percentage/BasicCell.tsx
new file mode 100644
index 000000000..b6036079d
--- /dev/null
+++ b/src/components/fields/Percentage/BasicCell.tsx
@@ -0,0 +1,41 @@
+import { IBasicCellProps } from "../types";
+
+import { useTheme } from "@material-ui/core";
+import { resultColorsScale } from "utils/color";
+
+export default function Percentage({ value }: IBasicCellProps) {
+ const theme = useTheme();
+
+ if (typeof value === "number")
+ return (
+ <>
+
+
+ {Math.round(value * 100)}%
+
+ >
+ );
+
+ return null;
+}
diff --git a/src/components/fields/Percentage/SideDrawerField.tsx b/src/components/fields/Percentage/SideDrawerField.tsx
new file mode 100644
index 000000000..b072302b0
--- /dev/null
+++ b/src/components/fields/Percentage/SideDrawerField.tsx
@@ -0,0 +1,71 @@
+import { Controller, useWatch } from "react-hook-form";
+import { ISideDrawerFieldProps } from "../types";
+
+import { makeStyles, createStyles } from "@material-ui/styles";
+import { TextField } from "@material-ui/core";
+import { emphasize } from "@material-ui/core/styles";
+import { resultColorsScale } from "utils/color";
+
+const useStyles = makeStyles((theme) =>
+ createStyles({
+ resultColor: ({ value }: { value: number | undefined }) => ({
+ backgroundColor:
+ typeof value === "number"
+ ? resultColorsScale(value).hex() + "!important"
+ : undefined,
+ color:
+ typeof value === "number"
+ ? emphasize(resultColorsScale(value).hex(), 1) + "!important"
+ : undefined,
+ }),
+
+ underline: {
+ "&::after": {
+ borderColor: theme.palette.text.primary,
+ },
+ },
+ })
+);
+
+export default function Percentage({
+ control,
+ column,
+ disabled,
+}: ISideDrawerFieldProps) {
+ const value: number | undefined = useWatch({ control, name: column.key });
+ const classes = useStyles({ value });
+
+ return (
+ {
+ const handleChange = (e) => onChange(Number(e.target.value) / 100);
+
+ return (
+
+ );
+ }}
+ />
+ );
+}
diff --git a/src/components/fields/Percentage/index.tsx b/src/components/fields/Percentage/index.tsx
new file mode 100644
index 000000000..23d2934ab
--- /dev/null
+++ b/src/components/fields/Percentage/index.tsx
@@ -0,0 +1,36 @@
+import { lazy } from "react";
+import { IFieldConfig, FieldType } from "components/fields/types";
+import withBasicCell from "../_withTableCell/withBasicCell";
+
+import PercentageIcon from "assets/icons/Percentage";
+import BasicCell from "./BasicCell";
+import TextEditor from "components/Table/editors/TextEditor";
+
+const SideDrawerField = lazy(
+ () =>
+ import(
+ "./SideDrawerField" /* webpackChunkName: "SideDrawerField-Percentage" */
+ )
+);
+
+export const config: IFieldConfig = {
+ type: FieldType.percentage,
+ name: "Percentage",
+ dataType: "number",
+ initialValue: 0,
+ initializable: true,
+ icon: ,
+ description: "Percentage stored as a number between 0 and 1.",
+ TableCell: withBasicCell(BasicCell),
+ TableEditor: TextEditor,
+ SideDrawerField,
+ csvImportParser: (v) => {
+ try {
+ const parsedValue = parseFloat(v);
+ return Number.isNaN(parsedValue) ? null : parsedValue;
+ } catch (e) {
+ return null;
+ }
+ },
+};
+export default config;
diff --git a/src/components/fields/Phone/SideDrawerField.tsx b/src/components/fields/Phone/SideDrawerField.tsx
new file mode 100644
index 000000000..36869189a
--- /dev/null
+++ b/src/components/fields/Phone/SideDrawerField.tsx
@@ -0,0 +1,39 @@
+import { Controller } from "react-hook-form";
+import { ISideDrawerFieldProps } from "../types";
+
+import { TextField } from "@material-ui/core";
+
+export default function Phone({
+ control,
+ column,
+ disabled,
+}: ISideDrawerFieldProps) {
+ return (
+ {
+ return (
+
+ );
+ }}
+ />
+ );
+}
diff --git a/www/src/components/fields/Phone/index.tsx b/src/components/fields/Phone/index.tsx
similarity index 52%
rename from www/src/components/fields/Phone/index.tsx
rename to src/components/fields/Phone/index.tsx
index 7d4e494fd..10bdeea0b 100644
--- a/www/src/components/fields/Phone/index.tsx
+++ b/src/components/fields/Phone/index.tsx
@@ -7,21 +7,21 @@ import BasicCell from "../_BasicCell/BasicCellValue";
import TextEditor from "components/Table/editors/TextEditor";
const SideDrawerField = lazy(
- () =>
- import("./SideDrawerField" /* webpackChunkName: "SideDrawerField-Phone" */)
+ () =>
+ import("./SideDrawerField" /* webpackChunkName: "SideDrawerField-Phone" */)
);
export const config: IFieldConfig = {
- type: FieldType.phone,
- name: "Phone",
- dataType: "string",
- initialValue: "",
- initializable: true,
- icon: ,
- description:
- "Phone numbers stored as text. Firetable does not validate phone numbers.",
- TableCell: withBasicCell(BasicCell),
- TableEditor: TextEditor,
- SideDrawerField,
+ type: FieldType.phone,
+ name: "Phone",
+ dataType: "string",
+ initialValue: "",
+ initializable: true,
+ icon: ,
+ description:
+ "Phone numbers stored as text. Rowy does not validate phone numbers.",
+ TableCell: withBasicCell(BasicCell),
+ TableEditor: TextEditor,
+ SideDrawerField,
};
export default config;
diff --git a/src/components/fields/Rating/Settings.tsx b/src/components/fields/Rating/Settings.tsx
new file mode 100644
index 000000000..2ce66a753
--- /dev/null
+++ b/src/components/fields/Rating/Settings.tsx
@@ -0,0 +1,41 @@
+import { ISettingsProps } from "../types";
+
+import { Slider } from "@material-ui/core";
+import Subheading from "components/Table/ColumnMenu/Subheading";
+
+export default function Settings({ handleChange, config }: ISettingsProps) {
+ return (
+ <>
+ Maximum number of stars
+ `${v} max stars`}
+ aria-labelledby="max-slider"
+ valueLabelDisplay="auto"
+ onChange={(_, v) => {
+ handleChange("max")(v);
+ }}
+ step={1}
+ marks
+ min={1}
+ max={15}
+ />
+