From 197e20f503e75ab0f59ab29c825d2358cfb3c4ce Mon Sep 17 00:00:00 2001 From: Filippo Ledda <46561561+filippomc@users.noreply.github.com> Date: Mon, 1 Mar 2021 10:59:31 +0100 Subject: [PATCH] Feature/0.3.0 (#244) * #58 fix: changed keyUsage to nonRepudiation, digitalSignature, keyEncipherment (#59) * #55 Application overriding introduced * #54 Remove reference to other projects * #55 Implement directory merge to build images * #55 Use merge strategy * #55 Instantiate docker client only on run * #55 Fix merging * #55 Remove / from registry in helm chart * #55 Fix ingress for domain * #55 Fix auto-gatekeeper * #55 Fix dpaths typo in directorymerge operation * #55 Fix dpaths typo in directorymerge operation * #55 Debug CF pipeline * #55 Test if CF is caching docker layers * #54 Allow private keys as build-args * #55 Polish PR * #55 Polish PR Co-authored-by: rodriguez-facundo Co-authored-by: Filippo Ledda * chore: added application specific secrets to deploy/values.yaml and cloudharness utilities e.g. config harness: ... secrets: - name: secret_1 value: value_1 - name: secret_2 value: value_2 ... e.g. usage from cloudharness.utils.secrets import get_secret value_1 = get_secret("secret_1") print(f"Secret 1 value: {value_1}" * #62 Enable workflow tasks to mount an existing PVC (merge PR #63) * #63 chore: add zip extract to download task and use the default CH base image so all CH tools are present in the container * #62 chore: enable mounting existing PVC in an argo workflow * #62 fix: remove debug print() statement * #61 chore: rework so application secrets need to be created on deployment and not on install * #64 Bind gatekeeper to port 80, update docker image for gatekeeper * Workflow fixes * Default registry removed * #66 fix: added argo-service to proxy to the argo ui and changed the argo port * #66 chore: removed extra argo service entry and fixed argo values.yaml * #67 fix: issue with events not working * #68 fix: issue sentry handler not connecting to common rest api * #69 chore: added EventClient.async_consume for async consuming events from a topic * chore: changed loglevel to INFO * #69 fix: fix issues, added more robust exception handling, added new image notify-queue for doing queue notification * #70 SSL redirect option added * #71 fix: replace double or more trialing slashes for registry to only one slash * #71 fix: replace double or more trialing slashes for registry to only one slash * Improved deploy robustness on missing applications * #73 fix: add extra try except and sleep(10) to the thread when the kafka client is disconnected * #78 Add option to disable tls (#79) * #78 option to disable tls added * #78 add tls option to accounts configuration * #76 chore: added create kafka cluster on init * Feature/78 (#81) * #78 option to disable tls added * #78 revert unrelated change * #78 add tls option to accounts configuration * #78 Fix no-http with jupyterhub * #78 fix set auto gatekeeper secure cookie to false if tls is disabled * Fix letsencrypt error * fix letsencrypt * fix letsencrypt * #83 removed default reference to accounts application (#84) * #82 chore: add uri role mapping for auto gk pods to (un)secure uri paths * #86: added namespace to letsencrypt issuer name * #86: removed doulbe - from ClusterIssuer name letsencrypt * #88 add namespace to cluster default zookeeper hosts (#89) * #90 make ingress listen to the naked domain * #91 chore: added third parameter (folder) to the download extract task (#92) * #94 chore: changed ClusterRole to Cluster and added namespace * #100 fix: issue with filtering on getting applications by boolean filter True/False (#101) * Feature/96 Support multiple paths in codefresh generate script (#98) * #96 Support added to multiple directory in codefresh generator * #102 chore: add get Keycloak user, group and users support to CH (#103) * #102 chore: add get Keycloak user, group and users support to CH * #102 fix: added missing HOST variable * #102 chore: added get_current_user to get the current logged in user * #97 New directory merge implementation (#104) * #97 Directory merge do not change current deployment anymore * #97 Fix build with merge * #97 Fix build/codefresh with merge * #97 Add create merge directory if does not exist * #97 Merge copy preserving file attributes for better caching * #97 Fix build include regression * #105 chore: reworked keycloak client and added members to get_groups * #105 fix: replaced ifn credentials/url by mnp credentials/url * #105 chore: made get group and get admin client publicable * #105 chore: added python-keycloak==0.22.0 to setup requirements * #105 chore: reworked AuthClient to to use instance functions instead of static, added user has client role tests * #105 fix: replaced wrong values for default realm, host and user in CH keycloak client * #105 chore: some additions and bugfixes to CH keycloak library * Feature/110 (#112) * #110 Copy deployment-configuration with merge * #111 run codefresh generation with harness-deployment * Fix build parameter * fix: replace .get[...] by .get(...) * #113 chore: add keycloak create client and client role to ch common python lib * Version update * #115 chore: add/update/delete kc user attributes * #115 fix: removed try except for add, update and delete user attributes * #115 chore: add get users for client with a specific role * build(deps): Bump urllib3 in /libraries/cloudharness-common Bumps [urllib3](https://github.com/urllib3/urllib3) from 1.24.1 to 1.24.2. - [Release notes](https://github.com/urllib3/urllib3/releases) - [Changelog](https://github.com/urllib3/urllib3/blob/master/CHANGES.rst) - [Commits](https://github.com/urllib3/urllib3/compare/1.24.1...1.24.2) Signed-off-by: dependabot[bot] * build(deps): Bump cryptography in /libraries/cloudharness-common Bumps [cryptography](https://github.com/pyca/cryptography) from 2.6.1 to 3.2. - [Release notes](https://github.com/pyca/cryptography/releases) - [Changelog](https://github.com/pyca/cryptography/blob/master/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/2.6.1...3.2) Signed-off-by: dependabot[bot] * chore: added query parameter to keycloak get_users * #122 fix: point Louketo image to gcr.io/metacellllc/louketo-proxy:1.0.0 because of EOL Louketo * #124 fix: removed non-existing scope vpn-user from auto gatekeeper * #126 chore: upgrade to keycloak 11 * #128 fix: add missing pyjwt package dependency * hotfix: kafka NEEDS clusterroles because it needs access to the nodes * hotfix: fixed missing eventclient exception * hotfix: fix issue with missing self. for getting the consumer * hotfix: stop events threads on sig int * hotfix: fixed issue missing domain postfix for hostname * hotfix fixes issue connecting to kc outside the kubernetes cluster (eg for development) * hotfix: add namespace to the kafka clusterrole naming node-reader * hotfix fix for duplicate kafka-node-reader adding namespace as prefix * hotfix fix for duplicate kafka-node-reader adding namespace as prefix * #109 codefresh dev and production deployment generation implemented (#140) * #143 chore: reworked the keycloak refresh token usage (#144) * hotfix: fix to reconnect when authclient has no session * #131 start refactoring application generation * #135 chore: mongodb auto database implementation * #135 chore: add auto database postgresql support * #135 chore: paramterized the database images * #137 chore: optimalizations of helm template * #135 chore: add neo4j support * #135 chore: updated comment about supported database types * Feature/145 fix new deployment (#147) * #141 argo added as part of the installation * #141 argo gatekeeper enabled * #141 argo service accounts renamed to avoid cluster name clashes * #145 Fix deployment issues * #145 fix deployment overriding * #145 adjust quotes for codefresh variables * adjust quotes for codefresh variables * adjust quotes for codefresh variables * Exclude useless paths from build * Fix push step * Fix push step * Fix push step * Fix push step * Add approval stage on prod pipeline * Fix use build id in deployment creation * Fix deployment creation order * Fix deployment creation order * Remove cluster role(bindings) * #141 add argo chart * #23 revert cluster role on argo * Upgrade helm version on codefresh * #141 revert argo roles * Fix prod deploy * Fix prod deploy * #141 rollback argo * Update chart version * Fix publish registry url * #145 fix: reverted change Role and RoleBinding to ClusterRole and ClusterRoleBinding * #145 update argo version to fix issue behind gatekeeper * #241 Fix codefresh prod step override issue * #145 git tag step fixed * #241 git tag step fixed Co-authored-by: Zoran Sinnema * #131 start refactoring application generation * #131 backend application template-based creation added * #131 backend application with unicorn * #131 updated samples application with gunicorn * Logging errors fixed * #131 samples application missing files * Feature/145: new deployment and argo fixes (#148) * #141 argo added as part of the installation * #141 argo gatekeeper enabled * #141 argo service accounts renamed to avoid cluster name clashes * #145 Fix deployment issues * #145 fix deployment overriding * #145 adjust quotes for codefresh variables * adjust quotes for codefresh variables * adjust quotes for codefresh variables * Exclude useless paths from build * Fix push step * Add approval stage on prod pipeline * Fix use build id in deployment creation * Fix deployment creation order * Fix deployment creation order * Remove cluster role(bindings) * #141 add argo chart * #23 revert cluster role on argo * Upgrade helm version on codefresh * #141 revert argo roles * Fix prod deploy * Fix prod deploy * #141 rollback argo * Update chart version * Fix publish registry url * #145 fix: reverted change Role and RoleBinding to ClusterRole and ClusterRoleBinding * #145 update argo version to fix issue behind gatekeeper * #241 Fix codefresh prod step override issue * #145 git tag step fixed * #241 git tag step fixed * git tag step fixed * #145 argo cluster roles clashes fixed Co-authored-by: Zoran Sinnema * #131 samples application backend + frontend * #131 samples application backend + frontend * #131 Webapp base images * #131 Webapp application generation logic and templates * #131 Webapp application generation fixes * #131 Sample application new files * #131 Database application generation * Add cluster initialization script * Move client library * #131 improve interactive generation * fix base images * hotfix: changed the admin user name from mnp to admin * Temporarily revert ingress proxy * Workflows refactoring * #149 chore: implement extra paths for proxies to other services * #131 namespaced argo instance * Reduce minimum applications requests * Fix application retrieval * Reduce minimum applications requests * #132 samples api link * cleaning useless files * Improve extract-download chmod * Improve logging * #132 small improvement on application generation * #154 PR fixes * #72 Deployment dependencies implemented * #72 Fix deployment dependency templates * Web application scaffolding (#154) * #131 start refactoring application generation * #131 backend application template-based creation added * #131 backend application with gunicorn * #131 updated samples application with gunicorn * #132 Logging errors fixed * #131 samples application missing files * #131 samples application backend + frontend * #131 Webapp base images * #131 Webapp application generation logic and templates * #131 Sample application new files * #131 Database application generation * #132 Add cluster initialization script * #132 Move client library * #131 improve interactive generation * #132 fix base images * #132 Temporarily revert ingress proxy * #132 Workflows refactoring * #131 namespaced argo instance * #132 Reduce minimum applications requests * #132 Fix application retrieval * #132 Reduce minimum applications requests * #132 samples api link * #132 cleaning useless files * #132 Improve extract-download chmod * #132 Improve logging * #132 small improvement on application generation * #154 PR fixes * #149 chore: PR comment fix, added [] to the use_services * #159 fix main ingress assignment (#160) * #159 fix main ingress assignment * #159 set accounts as the main application * #159 Fix ingress control condition * #159 Fix ingress control condition * #159 Fix ingress control condition * hotfix: fixes ch utilities setup missing harness-deployment script, update README.md reflecting the fix * #136 Base environment specific variables implementation (#163) * #136 Environment specific values implemented * #136 Environment specific values on codefresh templates * #76 fix codefresh build dependencies * Fix -dtls parameter in deployment * #157 Add template for postgres backup deployment * #157 Run postgres backup pod as postgres user * #157 Add PVC for postgres backups * Fix commands in README * #157 Set resources of db backup by values.yaml * #166 add user roles to the single and all user(s) getters * #137 WIP: Example for CronJob DB backup * Use Kubernetes CronJob * Use DB specific backup tool * Compress and store as single on backup volume * Missing command to cleanup all backups older than X days if mor than Y backups are present * #155 Add liveness and readiness probe * #166 changes requested per PR * #166 changes as per PR review * #157 Move backup switch and schedule to global level * #157 Define separate DB/backup yaml files * #137 Add cleanup logic to mongo backup script * Use multiline strings with "|" and "heredoc" functionality to pass complete script as input * #157 Configure Postgres backup as CronJob * #137 Adapt retention logic of postgres backup to mongo * #137 Extract backup script to separate files * Use .Files object to inject backup.sh * #137 #157 Move backup options to global level * Except for resources, since we might want to configure this depending on the DB and depending on the data size * #137 Cleanup script * #171 Fix readinessProbe config (#172) * #157 #137 Move backup resources to global level * #137 Improve backup bash script * #176 chore: add a more elegant way to create topics, don't raise errors in case a topic exists * #168 chore: implement external smtp server and remove postfix from repo also some code cleanup (#174) * #168 chore: implement external smtp server and remove postfix from repo also some code cleanup * #168 chore: added global sentry dsn support to common * #168 fix: fixes issue with sentry redis deployment * #176 fix: removed obsolete return * #176 chore: update event client topic error handling * #176 chore: optimized topic creation * #178 chore: add DOMAIN as sentry environment (#179) * hotfix: add max version <2 to pyjwt, we don't support v2 * #181 Improvements to template loading and overriding (#182) * Restored broken legacy values setting * #134 Auto-generate docs with helm-docs * Add instructions to README * Annotate values.yaml with comments * Add generated docs file * Fix tls secret name (#184) * Remove dist folder exclusion * chore: set basic format for logger * Optional tagging on stage/production * Optional tagging on stage/production (#185) * Optional tagging on stage/production * Useless codefresh variable removed * REPO_TOKEN conditional added * Feature/optional tagging (#187) * Optional tagging on stage/production * Useless codefresh variable removed * REPO_TOKEN conditional added * #186 Don't require TLS in Keycloak if TLS is deactivated * Small fix on workflows api * #190 refactor auth api (#193) * #190 small hotfix * #164 Set Python module name in Dockerfile * #164 Restrict application name by regex * #164 Restrict application name by regex * Namespace assignment hotfix * hotfix: fixed AttributeError: 'dict' object has no attribute 'user' on CH auth keycloak * hotfix: added missing /auth/ to SERVER_URL for keycloak client * hotfix namespace parametrization in helm chart * hotfix registry default specification on codefresh build added * hotfix: fix for ingress warning/error message when not using http/tls * #197 Add first draft of resource map for auto deployments * chore: added accounts auth config to common * hotfix: fixes KeyError when TLS is not present * #200 Add command and args specification on auto deployment (#201) * #197 Use subPath and set mount to readOnly * We decided to use subPath since it's sufficient for pods to be restarted in order to receive configmap changes and to enable us to inject configuration files inside specific directories actively used by the application (e.g. Nginx config directory) * Add yaml example * #198 Migrate accounts app to cloudharness template * #198 Resolve & cleanup todos * #203 Add target port for auto-services (#204) * #205 fix: broken build ch base image, added installation of rust and cargo for building cryptography 3.4.5 on linux * #198 Cleanup attributes in accounts values.yaml * #208 adding auth to SERVER_URL (#209) * #152 Replace deprecated TTLSecondsAfterFinished with ttlStrategy * #152 Fix PEP 8 violations * #211 Improve build error messaging (#212) * #152 Cleanup test_workflow * #152 Fix broken workflow example * cloudharness library was used without being available. Use cloudharness-base image to make it available * #218 fix: fixes issue with conflicting jwt and pyjwt * #217 chore: migrated creation of events to default ch way * Update values.yaml * Add user and pw attribute back * #207 Convert Argo workflow to str * #196 Remove duplicated copy * #224 fix: increased resource (limits) of keycloak/accounts * Fix values overriding - gatekeeper discovery url (#227) * Feature/fix values override (#228) * Fix values overriding - gatekeeper discovery url * Fix values overriding - gatekeeper discovery url * Feature/199 (#229) * #192 Update volumemanager * #192 Update workflows to use gunicorn * #192 Update common application to use gunicorn * #192 Reduce cpu resource request * #199 #17 add auto config: skaffold and vscode debug * #192 Clean Dockerfile * #192 Remove unneeded routes * #199 Fix value names in skaffold generation * #199 #192 refactor application creation * #199 #192 refactor application creation * #199 Added Skaffold docs * #199 Update gitignore * #199 Update application generator templates * #199 Update flask applications post refactoring * Fix helm overriding with hyphens * #199 update volumemanager Dockerfile * #199 remove setup.py from default .dockerignore * #199 skaffold support improved. Jupyterhub fixes * #199 handle task images with Skaffold * #199 #229 PR adjustments * #199 fix configuration passing * #199 chore: remove sentry as dependency from common Co-authored-by: Lucas Rebscher Co-authored-by: Zoran Sinnema * Feature/233 (#236) * #233 Fix template merging regression * #233 Unit tests and small fixing * #233 Unit tests tox environment * #233 fix test * #233 add badge to prs * #233 improve helm tests * #233 fix default value assignment * #233 fix helm values overriding bug * #226 chore: accounts set max heap size * #226 chore: set max heapsize to max mem - 12.5% * #242 adding userGroups and realmRoles to members * Feature/234 (#238) * #233 Fix template merging regression * #233 Unit tests and small fixing * #233 Unit tests tox environment * #233 fix test * #233 add badge to prs * #233 improve helm tests * #233 fix default value assignment * #233 fix helm values overriding bug * #234 set retain reclaim policy to databases * #234 Change default backup schedule to 5 minutes * #234 Remove storage class from deployment * #234 revert database volume claim * #234 add affinity to db pods * Version update Co-authored-by: Zoran Sinnema Co-authored-by: Facu Co-authored-by: rodriguez-facundo Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Lucas Rebscher Co-authored-by: Dario Del Piano Co-authored-by: Dario <37704177+ddelpiano@users.noreply.github.com> Co-authored-by: Lucas Rebscher Co-authored-by: Lucas Rebscher --- .dockerignore | 3 +- .gitignore | 3 + README.md | 52 +- applications/accounts/Dockerfile | 2 +- .../accounts/deploy/resources/realm.json | 2 +- .../accounts/deploy/templates/configmap.yaml | 11 - .../deploy/templates/keycloak-postgres.yaml | 77 - .../accounts/deploy/templates/keycloak.yaml | 78 - applications/accounts/deploy/values.yaml | 80 +- applications/argo/deploy/README.md | 13 + applications/argo/deploy/charts/.helmignore | 21 + applications/argo/deploy/charts/Chart.yaml | 12 + applications/argo/deploy/charts/README.md | 27 + .../crds/cluster-workflow-template-crd.yaml | 23 + .../deploy/charts/crds/cron-workflow-crd.yaml | 23 + .../argo/deploy/charts/crds/workflow-crd.yaml | 33 + .../crds/workflow-eventbinding-crd.yaml | 19 + .../charts/crds/workflow-template-crd.yaml | 22 + .../argo/deploy/charts/templates/NOTES.txt | 16 + .../argo/deploy/charts/templates/_helpers.tpl | 16 + .../cluster-workflow-template-crd.yaml | 19 + .../charts/templates/cron-workflow-crd.yaml | 19 + .../templates/server-cluster-roles.yaml | 102 + .../deploy/charts/templates/server-crb.yaml | 33 + .../templates/server-deployment-pdb.yaml | 25 + .../charts/templates/server-deployment.yaml | 108 + .../deploy/charts/templates/server-sa.yaml | 8 + .../charts/templates/server-service.yaml | 33 + .../worfkflow-controller-secrets-access.yaml | 18 + .../templates/workflow-aggregate-roles.yaml | 89 + .../workflow-controller-cluster-roles.yaml | 123 + .../workflow-controller-config-map.yaml | 89 + .../templates/workflow-controller-crb.yaml | 40 + .../workflow-controller-deployment-pdb.yaml | 23 + .../workflow-controller-deployment.yaml | 91 + .../workflow-controller-minio-secret-crb.yaml | 25 + .../templates/workflow-controller-sa.yaml | 6 + .../workflow-controller-service.yaml | 38 + .../workflow-controller-servicemonitor.yaml | 33 + .../deploy/charts/templates/workflow-crd.yaml | 28 + .../deploy/charts/templates/workflow-rb.yaml | 19 + .../charts/templates/workflow-role.yaml | 25 + .../deploy/charts/templates/workflow-sa.yaml | 13 + .../templates/workflow-template-crd.yaml | 18 + applications/argo/deploy/charts/values.yaml | 314 + .../argo/deploy/templates/argo-sa.yaml | 30 +- applications/argo/deploy/values.yaml | 8 +- applications/common/api/openapi.yaml | 25 + applications/common/deploy/values.yaml | 38 +- applications/common/server/.dockerignore | 1 - applications/common/server/Dockerfile | 23 +- applications/common/server/common/__main__.py | 23 +- applications/common/server/common/config.py | 4 +- .../common/controllers/accounts_controller.py | 22 + .../common/controllers/sentry_controller.py | 47 +- applications/common/server/common/encoder.py | 20 - .../common/server/common/openapi/openapi.yaml | 47 +- .../common/server/common/repository/db.py | 4 +- applications/common/server/requirements.txt | 2 +- applications/common/server/setup.py | 3 +- applications/events/Dockerfile | 1 + .../events/deploy/templates/deployments.yml | 60 +- .../events/deploy/templates/roles.yml | 17 +- applications/events/deploy/values.yaml | 7 + .../deploy/templates/hub/deployment.yaml | 2 +- .../scheduling/user-scheduler/rbac.yaml | 10 +- applications/jupyterhub/deploy/values.yaml | 14 +- applications/samples/.dockerignore | 2 + applications/samples/Dockerfile | 33 + applications/samples/README.md | 3 - applications/samples/api/config.json | 4 +- applications/samples/api/samples.yaml | 20 +- .../samples/{server => backend}/.dockerignore | 0 .../samples/{server => backend}/.gitignore | 2 + .../.openapi-generator-ignore | 4 +- .../samples/{server => backend}/.travis.yml | 0 .../samples/{server => backend}/README.md | 6 +- .../samples/{server => backend}/git_push.sh | 0 applications/samples/backend/requirements.txt | 10 + .../samples/backend/samples/__init__.py | 5 + .../samples/backend/samples/__main__.py | 9 + .../samples/controllers}/__init__.py | 0 .../samples}/controllers/auth_controller.py | 4 +- .../controllers/security_controller_.py | 17 + .../samples/controllers/test_controller.py | 27 + .../controllers/workflows_controller.py | 80 + .../backend/samples/models/__init__.py | 8 + .../samples}/models/base_model_.py | 2 +- .../samples}/models/inline_response202.py | 8 +- .../models/inline_response202_task.py | 4 +- .../samples}/models/valid.py | 4 +- .../samples}/openapi/openapi.yaml | 28 +- .../samples/service}/__init__.py | 0 .../samples}/service/security_service.py | 0 .../samples}/test/__init__.py | 2 +- .../samples}/test/test_auth_controller.py | 17 +- .../samples/test/test_test_controller.py | 47 + .../samples/test/test_workflows_controller.py | 66 + .../samples}/typing_utils.py | 0 .../api_samples => backend/samples}/util.py | 2 +- .../samples/{server => backend}/setup.py | 4 +- .../{server => backend}/test-requirements.txt | 2 +- .../samples/{server => backend}/tox.ini | 4 +- .../samples/deploy/resources/example.yaml | 3 + .../samples/deploy/resources/myConfig.json | 3 + applications/samples/deploy/values-prod.yaml | 5 + applications/samples/deploy/values.yaml | 19 + applications/samples/frontend/.babelrc | 20 + applications/samples/frontend/.dockerignore | 1 + applications/samples/frontend/.eslintignore | 1 + applications/samples/frontend/.eslintrc.yml | 49 + applications/samples/frontend/.gitignore | 4 + applications/samples/frontend/README.md | 1 + applications/samples/frontend/build.yaml | 2 + .../samples/frontend/package-lock.json | 8800 +++++++++++++++++ applications/samples/frontend/package.json | 58 + applications/samples/frontend/src/App.tsx | 16 + .../samples/frontend/src/assets/icon.png | Bin 0 -> 35505 bytes .../frontend/src/components/RestTest.tsx | 17 + applications/samples/frontend/src/index.ejs | 10 + applications/samples/frontend/src/index.tsx | 6 + .../samples/frontend/src/rest/.gitignore | 4 + .../samples/frontend/src/rest/.npmignore | 1 + .../src/rest/.openapi-generator-ignore | 23 + applications/samples/frontend/src/rest/api.ts | 620 ++ .../samples/frontend/src/rest/base.ts | 71 + .../frontend/src/rest/configuration.ts | 101 + .../samples/frontend/src/rest/git_push.sh | 58 + .../samples/frontend/src/rest/index.ts | 18 + .../samples/frontend/src/styles/style.less | 4 + .../samples/frontend/src/utils/history.js | 2 + applications/samples/frontend/tsconfig.json | 22 + .../samples/frontend/webpack.config.dev.js | 45 + .../samples/frontend/webpack.config.js | 110 + applications/samples/server/Dockerfile | 18 - .../samples/server/api_samples/__main__.py | 18 - .../controllers/workflows_controller.py | 83 - .../samples/server/api_samples/encoder.py | 20 - .../server/api_samples/models/__init__.py | 8 - .../test/test_default_controller.py | 40 - .../test/test_workflows_controller.py | 40 - applications/samples/server/requirements.txt | 7 - applications/samples/server/www/index.html | 1 - applications/sentry/Dockerfile | 11 +- .../sentry/deploy/templates/postfix.yaml | 61 - .../sentry/deploy/templates/postgres.yaml | 77 - .../sentry/deploy/templates/redis.yaml | 6 +- .../sentry/deploy/templates/secret.yaml | 10 + applications/sentry/deploy/values.yaml | 36 +- applications/sentry/sentryrunner.sh | 11 +- applications/volumemanager/deploy/values.yaml | 23 +- .../volumemanager/server/.dockerignore | 1 - applications/volumemanager/server/Dockerfile | 17 +- .../server/volumemanager/__main__.py | 13 +- .../server/volumemanager/encoder.py | 20 - applications/workflows/api/workflows.yaml | 2 +- applications/workflows/deploy/values.yaml | 7 +- applications/workflows/server/.dockerignore | 1 - applications/workflows/server/Dockerfile | 14 +- .../workflows/server/requirements.txt | 1 + applications/workflows/server/setup.py | 3 +- .../server/workflows_api/__main__.py | 16 +- .../create_and_access_controller.py | 4 +- .../server/workflows_api/openapi/openapi.yaml | 2 +- .../workflows_api/service/workflow_service.py | 10 +- .../workflows/tasks/extract-download/main.py | 41 +- .../workflows/tasks/print-file/Dockerfile | 4 +- .../workflows/tasks/print-file/main.py | 6 +- .../workflows/tasks/send-result-event/main.py | 8 +- blueprint/application-templates/README.md | 7 + .../cloudharness_cli.egg-info/PKG-INFO | 12 - .../cloudharness_cli.egg-info/SOURCES.txt | 40 - .../dependency_links.txt | 1 - .../cloudharness_cli.egg-info/requires.txt | 4 - .../cloudharness_cli.egg-info/top_level.txt | 1 - .../cloudharness-base-debian/Dockerfile | 9 +- .../base-images/cloudharness-base/Dockerfile | 17 +- .../cloudharness-frontend-build/Dockerfile | 3 + .../cloudharness-frontend-build/README.md | 3 + .../cluster-configuration/README.md | 4 + .../cluster-configuration/cluster-init.sh | 3 + .../cluster-configuration/ingress/values.yaml | 7 + .../cluster-configuration/storageclass.yaml | 8 + .../cloudharness-flask/Dockerfile | 19 + .../cloudharness-flask/requirements.txt | 6 + .../client}/cloudharness_cli/README.md | 0 .../cloudharness_cli}/__init__.py | 0 .../cloudharness_cli/common/__init__.py | 0 .../cloudharness_cli/common/api/__init__.py | 0 .../cloudharness_cli/common/api/sentry_api.py | 0 .../cloudharness_cli/common/api_client.py | 0 .../cloudharness_cli/common/configuration.py | 0 .../cloudharness_cli/common/exceptions.py | 0 .../common/models/__init__.py | 0 .../cloudharness_cli/common/rest.py | 0 .../cloudharness_cli/samples/__init__.py | 0 .../cloudharness_cli/samples/api/__init__.py | 0 .../cloudharness_cli/samples/api/auth_api.py | 0 .../samples/api/workflows_api.py | 0 .../cloudharness_cli/samples/api_client.py | 0 .../cloudharness_cli/samples/configuration.py | 0 .../cloudharness_cli/samples/exceptions.py | 0 .../samples/models/__init__.py | 0 .../samples/models/inline_response202.py | 0 .../samples/models/inline_response202_task.py | 0 .../cloudharness_cli/samples/models/valid.py | 0 .../cloudharness_cli/samples/rest.py | 0 .../cloudharness_cli/workflows/__init__.py | 0 .../workflows/api/__init__.py | 0 .../workflows/api/create_and_access_api.py | 0 .../cloudharness_cli/workflows/api_client.py | 0 .../workflows/configuration.py | 0 .../cloudharness_cli/workflows/exceptions.py | 0 .../workflows/models/__init__.py | 0 .../workflows/models/operation.py | 0 .../models/operation_search_result.py | 0 .../workflows/models/operation_status.py | 0 .../workflows/models/search_result_data.py | 0 .../cloudharness_cli/workflows/rest.py | 0 .../cloudharness_cli/docs/common/SentryApi.md | 0 .../cloudharness_cli/docs/samples/AuthApi.md | 0 .../docs/samples/InlineResponse202.md | 0 .../docs/samples/InlineResponse202Task.md | 0 .../cloudharness_cli/docs/samples/Valid.md | 0 .../docs/samples/WorkflowsApi.md | 0 .../docs/workflows/CreateAndAccessApi.md | 0 .../docs/workflows/Operation.md | 0 .../docs/workflows/OperationSearchResult.md | 0 .../docs/workflows/OperationStatus.md | 0 .../docs/workflows/SearchResultData.md | 0 .../client}/cloudharness_cli/requirements.txt | 0 .../client}/cloudharness_cli/setup.py | 0 .../cloudharness_cli/test-requirements.txt | 0 .../cloudharness_cli/test/common}/__init__.py | 0 .../test/common/test_sentry_api.py | 0 .../test/samples}/__init__.py | 0 .../test/samples/test_auth_api.py | 0 .../test/samples/test_inline_response202.py | 0 .../samples/test_inline_response202_task.py | 0 .../test/samples/test_valid.py | 0 .../test/samples/test_workflows_api.py | 0 .../test/workflows}/__init__.py | 0 .../workflows/test_create_and_access_api.py | 0 .../test/workflows/test_operation.py | 0 .../workflows/test_operation_search_result.py | 0 .../test/workflows/test_operation_status.py | 0 .../test/workflows/test_search_result_data.py | 0 .../cloudharness/__init__.py | 4 +- .../cloudharness/applications.py | 68 +- .../cloudharness/auth/keycloak/__init__.py | 174 +- .../cloudharness/events/client.py | 43 +- .../cloudharness/infrastructure}/__init__.py | 0 .../cloudharness/infrastructure/k8s.py | 114 + .../persistence/nosql_database/mongo.py | 0 .../cloudharness/sentry/__init__.py | 4 + .../cloudharness/utils/config.py | 24 +- .../cloudharness/utils/env.py | 7 +- .../cloudharness/utils/server.py | 91 + .../cloudharness/workflows/argo.py | 156 +- .../cloudharness/workflows/operations.py | 45 +- .../cloudharness/workflows/tasks.py | 16 +- .../cloudharness/workflows/utils.py | 6 +- .../cloudharness-common/requirements.txt | 6 +- libraries/cloudharness-common/setup.py | 8 +- .../cloudharness-common/test-requirements.txt | 2 + .../tests/test_applications.py | 10 +- .../cloudharness-common/tests/test_env.py | 33 +- .../tests/test_infrastructure.py | 13 + .../tests/test_integration.py | 2 +- .../tests/test_workflow.py | 115 +- .../cloudharness-common/tests/values.yaml | 1113 +++ utilities/MANIFEST.in | 6 +- utilities/README.md | 18 +- utilities/cloudharness_utilities/__init__.py | 2 +- .../application-template/api/config.json | 3 - .../application-template/api/openapi.yaml | 47 - .../application-template/deploy/values.yaml | 4 - .../application-templates/README.md | 7 + .../base/api/config.json | 3 + .../base/api/openapi.yaml | 75 + .../base/deploy/values.yaml | 17 + .../db-mongo/deploy/values.yaml | 4 + .../db-neo4j/deploy/values.yaml | 4 + .../db-postgres/deploy/values.yaml | 4 + .../server/backend/.dockerignore | 71 + .../server/backend/.openapi-generator-ignore | 29 + .../server/backend/Dockerfile | 19 + .../server/backend/README.md | 27 + .../server/backend/__APP_NAME__/__init__.py | 0 .../server/backend/__APP_NAME__/__main__.py | 10 + .../backend/__APP_NAME__/helpers/README.md | 4 + .../backend/__APP_NAME__/helpers/__init__.py | 0 .../backend/__APP_NAME__/services/README.md | 3 + .../backend/__APP_NAME__/services/__init__.py | 0 .../webapp/.dockerignore | 2 + .../application-templates/webapp/Dockerfile | 36 + .../application-templates/webapp/README.md | 68 + .../webapp/backend/__APP_NAME__/__main__.py | 10 + .../webapp/deploy/values.yaml | 6 + .../webapp/frontend/.babelrc | 20 + .../webapp/frontend/.dockerignore | 1 + .../webapp/frontend/.eslintignore | 2 + .../webapp/frontend/.eslintrc.yml | 49 + .../webapp/frontend/.gitignore | 4 + .../webapp/frontend/README.md | 1 + .../webapp/frontend/build.yaml | 2 + .../webapp/frontend/package-lock.json | 8800 +++++++++++++++++ .../webapp/frontend/package.json | 58 + .../webapp/frontend/src/App.tsx | 16 + .../webapp/frontend/src/assets/icon.png | Bin 0 -> 35505 bytes .../frontend/src/components/RestTest.tsx | 17 + .../webapp/frontend/src/index.ejs | 10 + .../webapp/frontend/src/index.tsx | 6 + .../webapp/frontend/src/styles/style.less | 4 + .../webapp/frontend/src/utils/history.js | 2 + .../webapp/frontend/tsconfig.json | 22 + .../webapp/frontend/webpack.config.dev.js | 45 + .../webapp/frontend/webpack.config.js | 110 + utilities/cloudharness_utilities/build.py | 55 +- utilities/cloudharness_utilities/codefresh.py | 132 +- utilities/cloudharness_utilities/constants.py | 22 +- .../deployment-configuration/README.md | 38 +- .../codefresh-build-template.yaml | 7 +- .../codefresh-publish-template.yaml | 7 + ...plate.yaml => codefresh-template-dev.yaml} | 30 +- .../codefresh-template-prod.yaml | 90 + .../deployment-configuration/docs.md | 49 + .../deployment-configuration/helm/Chart.yaml | 4 +- .../helm/files/db-mongo-backup.sh | 39 + .../templates/auto-database-mongo-backup.yaml | 64 + .../helm/templates/auto-database-mongo.yaml | 26 + .../templates/auto-database-neo4j-backup.yaml | 2 + .../helm/templates/auto-database-neo4j.yaml | 20 + .../auto-database-postgres-backup.yaml | 58 + .../templates/auto-database-postgres.yaml | 12 + .../helm/templates/auto-database.yaml | 124 + .../helm/templates/auto-deployments.yaml | 56 +- .../helm/templates/auto-gatekeepers.yaml | 7 +- .../helm/templates/auto-services.yaml | 1 + .../helm/templates/certs/letsencrypt.yaml | 4 +- .../helm/templates/ingress.yaml | 75 +- .../helm/templates/tls-secret.yaml | 2 +- .../deployment-configuration/helm/values.yaml | 73 + .../deployment-configuration/launch.json | 4 + .../skaffold-template.yaml | 23 + .../value-template.yaml | 82 +- .../values-template.yaml | 27 - .../vscode-debug-template.json | 13 + utilities/cloudharness_utilities/dev_utils.py | 159 + utilities/cloudharness_utilities/helm.py | 238 +- utilities/cloudharness_utilities/openapi.py | 25 +- utilities/cloudharness_utilities/utils.py | 199 +- utilities/harness-application | 50 +- utilities/harness-codefresh | 32 - utilities/harness-deployment | 52 +- utilities/harness-generate | 75 +- utilities/setup.py | 4 +- utilities/test-requirements.txt | 8 + .../accounts/deploy/resources/aresource.txt | 0 .../accounts/deploy/values-dev.yaml | 1 + .../applications/accounts/deploy/values.yaml | 5 + .../applications/legacy/deploy/values.yaml | 3 + .../resources/applications/myapp/Dockerfile | 0 .../myapp/deploy/resources/aresource.txt | 0 .../myapp/deploy/templates/mytemplate.yaml | 0 .../applications/myapp/deploy/values.yaml | 7 + .../value-template.yaml | 1 + .../values-template-dev.yaml | 3 + .../values-template.yaml | 5 + utilities/tests/test_helm.py | 72 + utilities/tests/test_utils.py | 5 +- utilities/tox.ini | 9 + 372 files changed, 25656 insertions(+), 1727 deletions(-) delete mode 100644 applications/accounts/deploy/templates/configmap.yaml delete mode 100644 applications/accounts/deploy/templates/keycloak-postgres.yaml delete mode 100644 applications/accounts/deploy/templates/keycloak.yaml create mode 100644 applications/argo/deploy/README.md create mode 100755 applications/argo/deploy/charts/.helmignore create mode 100755 applications/argo/deploy/charts/Chart.yaml create mode 100755 applications/argo/deploy/charts/README.md create mode 100644 applications/argo/deploy/charts/crds/cluster-workflow-template-crd.yaml create mode 100644 applications/argo/deploy/charts/crds/cron-workflow-crd.yaml create mode 100644 applications/argo/deploy/charts/crds/workflow-crd.yaml create mode 100644 applications/argo/deploy/charts/crds/workflow-eventbinding-crd.yaml create mode 100644 applications/argo/deploy/charts/crds/workflow-template-crd.yaml create mode 100644 applications/argo/deploy/charts/templates/NOTES.txt create mode 100644 applications/argo/deploy/charts/templates/_helpers.tpl create mode 100644 applications/argo/deploy/charts/templates/cluster-workflow-template-crd.yaml create mode 100644 applications/argo/deploy/charts/templates/cron-workflow-crd.yaml create mode 100644 applications/argo/deploy/charts/templates/server-cluster-roles.yaml create mode 100644 applications/argo/deploy/charts/templates/server-crb.yaml create mode 100644 applications/argo/deploy/charts/templates/server-deployment-pdb.yaml create mode 100644 applications/argo/deploy/charts/templates/server-deployment.yaml create mode 100644 applications/argo/deploy/charts/templates/server-sa.yaml create mode 100644 applications/argo/deploy/charts/templates/server-service.yaml create mode 100644 applications/argo/deploy/charts/templates/worfkflow-controller-secrets-access.yaml create mode 100644 applications/argo/deploy/charts/templates/workflow-aggregate-roles.yaml create mode 100644 applications/argo/deploy/charts/templates/workflow-controller-cluster-roles.yaml create mode 100644 applications/argo/deploy/charts/templates/workflow-controller-config-map.yaml create mode 100644 applications/argo/deploy/charts/templates/workflow-controller-crb.yaml create mode 100644 applications/argo/deploy/charts/templates/workflow-controller-deployment-pdb.yaml create mode 100755 applications/argo/deploy/charts/templates/workflow-controller-deployment.yaml create mode 100644 applications/argo/deploy/charts/templates/workflow-controller-minio-secret-crb.yaml create mode 100644 applications/argo/deploy/charts/templates/workflow-controller-sa.yaml create mode 100644 applications/argo/deploy/charts/templates/workflow-controller-service.yaml create mode 100644 applications/argo/deploy/charts/templates/workflow-controller-servicemonitor.yaml create mode 100644 applications/argo/deploy/charts/templates/workflow-crd.yaml create mode 100644 applications/argo/deploy/charts/templates/workflow-rb.yaml create mode 100644 applications/argo/deploy/charts/templates/workflow-role.yaml create mode 100644 applications/argo/deploy/charts/templates/workflow-sa.yaml create mode 100644 applications/argo/deploy/charts/templates/workflow-template-crd.yaml create mode 100755 applications/argo/deploy/charts/values.yaml create mode 100644 applications/common/server/common/controllers/accounts_controller.py delete mode 100644 applications/common/server/common/encoder.py create mode 100644 applications/events/Dockerfile create mode 100644 applications/samples/.dockerignore create mode 100644 applications/samples/Dockerfile rename applications/samples/{server => backend}/.dockerignore (100%) rename applications/samples/{server => backend}/.gitignore (99%) rename applications/samples/{server => backend}/.openapi-generator-ignore (97%) rename applications/samples/{server => backend}/.travis.yml (100%) rename applications/samples/{server => backend}/README.md (88%) rename applications/samples/{server => backend}/git_push.sh (100%) create mode 100644 applications/samples/backend/requirements.txt create mode 100644 applications/samples/backend/samples/__init__.py create mode 100644 applications/samples/backend/samples/__main__.py rename applications/samples/{server/api_samples => backend/samples/controllers}/__init__.py (100%) rename applications/samples/{server/api_samples => backend/samples}/controllers/auth_controller.py (73%) create mode 100644 applications/samples/backend/samples/controllers/security_controller_.py create mode 100644 applications/samples/backend/samples/controllers/test_controller.py create mode 100644 applications/samples/backend/samples/controllers/workflows_controller.py create mode 100644 applications/samples/backend/samples/models/__init__.py rename applications/samples/{server/api_samples => backend/samples}/models/base_model_.py (98%) rename applications/samples/{server/api_samples => backend/samples}/models/inline_response202.py (86%) rename applications/samples/{server/api_samples => backend/samples}/models/inline_response202_task.py (96%) rename applications/samples/{server/api_samples => backend/samples}/models/valid.py (94%) rename applications/samples/{server/api_samples => backend/samples}/openapi/openapi.yaml (82%) rename applications/samples/{server/api_samples/controllers => backend/samples/service}/__init__.py (100%) rename applications/samples/{server/api_samples => backend/samples}/service/security_service.py (100%) rename applications/samples/{server/api_samples => backend/samples}/test/__init__.py (89%) rename applications/samples/{server/api_samples => backend/samples}/test/test_auth_controller.py (54%) create mode 100644 applications/samples/backend/samples/test/test_test_controller.py create mode 100644 applications/samples/backend/samples/test/test_workflows_controller.py rename applications/samples/{server/api_samples => backend/samples}/typing_utils.py (100%) rename applications/samples/{server/api_samples => backend/samples}/util.py (98%) rename applications/samples/{server => backend}/setup.py (89%) rename applications/samples/{server => backend}/test-requirements.txt (84%) rename applications/samples/{server => backend}/tox.ini (62%) create mode 100644 applications/samples/deploy/resources/example.yaml create mode 100644 applications/samples/deploy/resources/myConfig.json create mode 100644 applications/samples/deploy/values-prod.yaml create mode 100644 applications/samples/frontend/.babelrc create mode 100644 applications/samples/frontend/.dockerignore create mode 100644 applications/samples/frontend/.eslintignore create mode 100644 applications/samples/frontend/.eslintrc.yml create mode 100644 applications/samples/frontend/.gitignore create mode 100644 applications/samples/frontend/README.md create mode 100644 applications/samples/frontend/build.yaml create mode 100644 applications/samples/frontend/package-lock.json create mode 100644 applications/samples/frontend/package.json create mode 100644 applications/samples/frontend/src/App.tsx create mode 100644 applications/samples/frontend/src/assets/icon.png create mode 100644 applications/samples/frontend/src/components/RestTest.tsx create mode 100644 applications/samples/frontend/src/index.ejs create mode 100644 applications/samples/frontend/src/index.tsx create mode 100644 applications/samples/frontend/src/rest/.gitignore create mode 100644 applications/samples/frontend/src/rest/.npmignore create mode 100644 applications/samples/frontend/src/rest/.openapi-generator-ignore create mode 100644 applications/samples/frontend/src/rest/api.ts create mode 100644 applications/samples/frontend/src/rest/base.ts create mode 100644 applications/samples/frontend/src/rest/configuration.ts create mode 100644 applications/samples/frontend/src/rest/git_push.sh create mode 100644 applications/samples/frontend/src/rest/index.ts create mode 100644 applications/samples/frontend/src/styles/style.less create mode 100644 applications/samples/frontend/src/utils/history.js create mode 100755 applications/samples/frontend/tsconfig.json create mode 100644 applications/samples/frontend/webpack.config.dev.js create mode 100644 applications/samples/frontend/webpack.config.js delete mode 100644 applications/samples/server/Dockerfile delete mode 100644 applications/samples/server/api_samples/__main__.py delete mode 100644 applications/samples/server/api_samples/controllers/workflows_controller.py delete mode 100644 applications/samples/server/api_samples/encoder.py delete mode 100644 applications/samples/server/api_samples/models/__init__.py delete mode 100644 applications/samples/server/api_samples/test/test_default_controller.py delete mode 100644 applications/samples/server/api_samples/test/test_workflows_controller.py delete mode 100644 applications/samples/server/requirements.txt delete mode 100644 applications/samples/server/www/index.html delete mode 100644 applications/sentry/deploy/templates/postfix.yaml delete mode 100644 applications/sentry/deploy/templates/postgres.yaml create mode 100644 applications/sentry/deploy/templates/secret.yaml delete mode 100644 applications/volumemanager/server/volumemanager/encoder.py create mode 100644 blueprint/application-templates/README.md delete mode 100644 client/cloudharness_cli/cloudharness_cli.egg-info/PKG-INFO delete mode 100644 client/cloudharness_cli/cloudharness_cli.egg-info/SOURCES.txt delete mode 100644 client/cloudharness_cli/cloudharness_cli.egg-info/dependency_links.txt delete mode 100644 client/cloudharness_cli/cloudharness_cli.egg-info/requires.txt delete mode 100644 client/cloudharness_cli/cloudharness_cli.egg-info/top_level.txt create mode 100644 infrastructure/base-images/cloudharness-frontend-build/Dockerfile create mode 100644 infrastructure/base-images/cloudharness-frontend-build/README.md create mode 100644 infrastructure/cluster-configuration/README.md create mode 100644 infrastructure/cluster-configuration/cluster-init.sh create mode 100644 infrastructure/cluster-configuration/ingress/values.yaml create mode 100644 infrastructure/cluster-configuration/storageclass.yaml create mode 100644 infrastructure/common-images/cloudharness-flask/Dockerfile create mode 100644 infrastructure/common-images/cloudharness-flask/requirements.txt rename {client => libraries/client}/cloudharness_cli/README.md (100%) rename {applications/samples/server/api_samples/service => libraries/client/cloudharness_cli/cloudharness_cli}/__init__.py (100%) rename {client => libraries/client}/cloudharness_cli/cloudharness_cli/common/__init__.py (100%) rename {client => libraries/client}/cloudharness_cli/cloudharness_cli/common/api/__init__.py (100%) rename {client => libraries/client}/cloudharness_cli/cloudharness_cli/common/api/sentry_api.py (100%) rename {client => libraries/client}/cloudharness_cli/cloudharness_cli/common/api_client.py (100%) rename {client => libraries/client}/cloudharness_cli/cloudharness_cli/common/configuration.py (100%) rename {client => libraries/client}/cloudharness_cli/cloudharness_cli/common/exceptions.py (100%) rename {client => libraries/client}/cloudharness_cli/cloudharness_cli/common/models/__init__.py (100%) rename {client => libraries/client}/cloudharness_cli/cloudharness_cli/common/rest.py (100%) rename {client => libraries/client}/cloudharness_cli/cloudharness_cli/samples/__init__.py (100%) rename {client => libraries/client}/cloudharness_cli/cloudharness_cli/samples/api/__init__.py (100%) rename {client => libraries/client}/cloudharness_cli/cloudharness_cli/samples/api/auth_api.py (100%) rename {client => libraries/client}/cloudharness_cli/cloudharness_cli/samples/api/workflows_api.py (100%) rename {client => libraries/client}/cloudharness_cli/cloudharness_cli/samples/api_client.py (100%) rename {client => libraries/client}/cloudharness_cli/cloudharness_cli/samples/configuration.py (100%) rename {client => libraries/client}/cloudharness_cli/cloudharness_cli/samples/exceptions.py (100%) rename {client => libraries/client}/cloudharness_cli/cloudharness_cli/samples/models/__init__.py (100%) rename {client => libraries/client}/cloudharness_cli/cloudharness_cli/samples/models/inline_response202.py (100%) rename {client => libraries/client}/cloudharness_cli/cloudharness_cli/samples/models/inline_response202_task.py (100%) rename {client => libraries/client}/cloudharness_cli/cloudharness_cli/samples/models/valid.py (100%) rename {client => libraries/client}/cloudharness_cli/cloudharness_cli/samples/rest.py (100%) rename {client => libraries/client}/cloudharness_cli/cloudharness_cli/workflows/__init__.py (100%) rename {client => libraries/client}/cloudharness_cli/cloudharness_cli/workflows/api/__init__.py (100%) rename {client => libraries/client}/cloudharness_cli/cloudharness_cli/workflows/api/create_and_access_api.py (100%) rename {client => libraries/client}/cloudharness_cli/cloudharness_cli/workflows/api_client.py (100%) rename {client => libraries/client}/cloudharness_cli/cloudharness_cli/workflows/configuration.py (100%) rename {client => libraries/client}/cloudharness_cli/cloudharness_cli/workflows/exceptions.py (100%) rename {client => libraries/client}/cloudharness_cli/cloudharness_cli/workflows/models/__init__.py (100%) rename {client => libraries/client}/cloudharness_cli/cloudharness_cli/workflows/models/operation.py (100%) rename {client => libraries/client}/cloudharness_cli/cloudharness_cli/workflows/models/operation_search_result.py (100%) rename {client => libraries/client}/cloudharness_cli/cloudharness_cli/workflows/models/operation_status.py (100%) rename {client => libraries/client}/cloudharness_cli/cloudharness_cli/workflows/models/search_result_data.py (100%) rename {client => libraries/client}/cloudharness_cli/cloudharness_cli/workflows/rest.py (100%) rename {client => libraries/client}/cloudharness_cli/docs/common/SentryApi.md (100%) rename {client => libraries/client}/cloudharness_cli/docs/samples/AuthApi.md (100%) rename {client => libraries/client}/cloudharness_cli/docs/samples/InlineResponse202.md (100%) rename {client => libraries/client}/cloudharness_cli/docs/samples/InlineResponse202Task.md (100%) rename {client => libraries/client}/cloudharness_cli/docs/samples/Valid.md (100%) rename {client => libraries/client}/cloudharness_cli/docs/samples/WorkflowsApi.md (100%) rename {client => libraries/client}/cloudharness_cli/docs/workflows/CreateAndAccessApi.md (100%) rename {client => libraries/client}/cloudharness_cli/docs/workflows/Operation.md (100%) rename {client => libraries/client}/cloudharness_cli/docs/workflows/OperationSearchResult.md (100%) rename {client => libraries/client}/cloudharness_cli/docs/workflows/OperationStatus.md (100%) rename {client => libraries/client}/cloudharness_cli/docs/workflows/SearchResultData.md (100%) rename {client => libraries/client}/cloudharness_cli/requirements.txt (100%) rename {client => libraries/client}/cloudharness_cli/setup.py (100%) rename {client => libraries/client}/cloudharness_cli/test-requirements.txt (100%) rename {applications/workflows/server => libraries/client/cloudharness_cli/test/common}/__init__.py (100%) rename {client => libraries/client}/cloudharness_cli/test/common/test_sentry_api.py (100%) rename {client/cloudharness_cli/cloudharness_cli => libraries/client/cloudharness_cli/test/samples}/__init__.py (100%) rename {client => libraries/client}/cloudharness_cli/test/samples/test_auth_api.py (100%) rename {client => libraries/client}/cloudharness_cli/test/samples/test_inline_response202.py (100%) rename {client => libraries/client}/cloudharness_cli/test/samples/test_inline_response202_task.py (100%) rename {client => libraries/client}/cloudharness_cli/test/samples/test_valid.py (100%) rename {client => libraries/client}/cloudharness_cli/test/samples/test_workflows_api.py (100%) rename {client/cloudharness_cli/test/common => libraries/client/cloudharness_cli/test/workflows}/__init__.py (100%) rename {client => libraries/client}/cloudharness_cli/test/workflows/test_create_and_access_api.py (100%) rename {client => libraries/client}/cloudharness_cli/test/workflows/test_operation.py (100%) rename {client => libraries/client}/cloudharness_cli/test/workflows/test_operation_search_result.py (100%) rename {client => libraries/client}/cloudharness_cli/test/workflows/test_operation_status.py (100%) rename {client => libraries/client}/cloudharness_cli/test/workflows/test_search_result_data.py (100%) rename {client/cloudharness_cli/test/samples => libraries/cloudharness-common/cloudharness/infrastructure}/__init__.py (100%) create mode 100644 libraries/cloudharness-common/cloudharness/infrastructure/k8s.py rename client/cloudharness_cli/test/workflows/__init__.py => libraries/cloudharness-common/cloudharness/persistence/nosql_database/mongo.py (100%) create mode 100644 libraries/cloudharness-common/cloudharness/utils/server.py create mode 100644 libraries/cloudharness-common/tests/test_infrastructure.py create mode 100644 libraries/cloudharness-common/tests/values.yaml delete mode 100644 utilities/cloudharness_utilities/application-template/api/config.json delete mode 100644 utilities/cloudharness_utilities/application-template/api/openapi.yaml delete mode 100644 utilities/cloudharness_utilities/application-template/deploy/values.yaml create mode 100644 utilities/cloudharness_utilities/application-templates/README.md create mode 100644 utilities/cloudharness_utilities/application-templates/base/api/config.json create mode 100644 utilities/cloudharness_utilities/application-templates/base/api/openapi.yaml create mode 100644 utilities/cloudharness_utilities/application-templates/base/deploy/values.yaml create mode 100644 utilities/cloudharness_utilities/application-templates/db-mongo/deploy/values.yaml create mode 100644 utilities/cloudharness_utilities/application-templates/db-neo4j/deploy/values.yaml create mode 100644 utilities/cloudharness_utilities/application-templates/db-postgres/deploy/values.yaml create mode 100644 utilities/cloudharness_utilities/application-templates/server/backend/.dockerignore create mode 100644 utilities/cloudharness_utilities/application-templates/server/backend/.openapi-generator-ignore create mode 100644 utilities/cloudharness_utilities/application-templates/server/backend/Dockerfile create mode 100644 utilities/cloudharness_utilities/application-templates/server/backend/README.md create mode 100644 utilities/cloudharness_utilities/application-templates/server/backend/__APP_NAME__/__init__.py create mode 100644 utilities/cloudharness_utilities/application-templates/server/backend/__APP_NAME__/__main__.py create mode 100644 utilities/cloudharness_utilities/application-templates/server/backend/__APP_NAME__/helpers/README.md create mode 100644 utilities/cloudharness_utilities/application-templates/server/backend/__APP_NAME__/helpers/__init__.py create mode 100644 utilities/cloudharness_utilities/application-templates/server/backend/__APP_NAME__/services/README.md create mode 100644 utilities/cloudharness_utilities/application-templates/server/backend/__APP_NAME__/services/__init__.py create mode 100644 utilities/cloudharness_utilities/application-templates/webapp/.dockerignore create mode 100644 utilities/cloudharness_utilities/application-templates/webapp/Dockerfile create mode 100644 utilities/cloudharness_utilities/application-templates/webapp/README.md create mode 100644 utilities/cloudharness_utilities/application-templates/webapp/backend/__APP_NAME__/__main__.py create mode 100644 utilities/cloudharness_utilities/application-templates/webapp/deploy/values.yaml create mode 100644 utilities/cloudharness_utilities/application-templates/webapp/frontend/.babelrc create mode 100644 utilities/cloudharness_utilities/application-templates/webapp/frontend/.dockerignore create mode 100644 utilities/cloudharness_utilities/application-templates/webapp/frontend/.eslintignore create mode 100644 utilities/cloudharness_utilities/application-templates/webapp/frontend/.eslintrc.yml create mode 100644 utilities/cloudharness_utilities/application-templates/webapp/frontend/.gitignore create mode 100644 utilities/cloudharness_utilities/application-templates/webapp/frontend/README.md create mode 100644 utilities/cloudharness_utilities/application-templates/webapp/frontend/build.yaml create mode 100644 utilities/cloudharness_utilities/application-templates/webapp/frontend/package-lock.json create mode 100644 utilities/cloudharness_utilities/application-templates/webapp/frontend/package.json create mode 100644 utilities/cloudharness_utilities/application-templates/webapp/frontend/src/App.tsx create mode 100644 utilities/cloudharness_utilities/application-templates/webapp/frontend/src/assets/icon.png create mode 100644 utilities/cloudharness_utilities/application-templates/webapp/frontend/src/components/RestTest.tsx create mode 100644 utilities/cloudharness_utilities/application-templates/webapp/frontend/src/index.ejs create mode 100644 utilities/cloudharness_utilities/application-templates/webapp/frontend/src/index.tsx create mode 100644 utilities/cloudharness_utilities/application-templates/webapp/frontend/src/styles/style.less create mode 100644 utilities/cloudharness_utilities/application-templates/webapp/frontend/src/utils/history.js create mode 100755 utilities/cloudharness_utilities/application-templates/webapp/frontend/tsconfig.json create mode 100644 utilities/cloudharness_utilities/application-templates/webapp/frontend/webpack.config.dev.js create mode 100644 utilities/cloudharness_utilities/application-templates/webapp/frontend/webpack.config.js create mode 100644 utilities/cloudharness_utilities/deployment-configuration/codefresh-publish-template.yaml rename utilities/cloudharness_utilities/deployment-configuration/{codefresh-template.yaml => codefresh-template-dev.yaml} (60%) create mode 100644 utilities/cloudharness_utilities/deployment-configuration/codefresh-template-prod.yaml create mode 100644 utilities/cloudharness_utilities/deployment-configuration/docs.md create mode 100644 utilities/cloudharness_utilities/deployment-configuration/helm/files/db-mongo-backup.sh create mode 100644 utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-database-mongo-backup.yaml create mode 100644 utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-database-mongo.yaml create mode 100644 utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-database-neo4j-backup.yaml create mode 100644 utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-database-neo4j.yaml create mode 100644 utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-database-postgres-backup.yaml create mode 100644 utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-database-postgres.yaml create mode 100644 utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-database.yaml create mode 100644 utilities/cloudharness_utilities/deployment-configuration/launch.json create mode 100644 utilities/cloudharness_utilities/deployment-configuration/skaffold-template.yaml create mode 100644 utilities/cloudharness_utilities/deployment-configuration/vscode-debug-template.json create mode 100644 utilities/cloudharness_utilities/dev_utils.py delete mode 100644 utilities/harness-codefresh create mode 100644 utilities/test-requirements.txt create mode 100644 utilities/tests/resources/applications/accounts/deploy/resources/aresource.txt create mode 100644 utilities/tests/resources/applications/accounts/deploy/values-dev.yaml create mode 100644 utilities/tests/resources/applications/accounts/deploy/values.yaml create mode 100644 utilities/tests/resources/applications/legacy/deploy/values.yaml create mode 100644 utilities/tests/resources/applications/myapp/Dockerfile create mode 100644 utilities/tests/resources/applications/myapp/deploy/resources/aresource.txt create mode 100644 utilities/tests/resources/applications/myapp/deploy/templates/mytemplate.yaml create mode 100644 utilities/tests/resources/applications/myapp/deploy/values.yaml create mode 100644 utilities/tests/resources/deployment-configuration/value-template.yaml create mode 100644 utilities/tests/resources/deployment-configuration/values-template-dev.yaml create mode 100644 utilities/tests/resources/deployment-configuration/values-template.yaml create mode 100644 utilities/tests/test_helm.py create mode 100644 utilities/tox.ini diff --git a/.dockerignore b/.dockerignore index 600e365e..b8130bc4 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1 +1,2 @@ -**/node_modules \ No newline at end of file +**/node_modules +.tox \ No newline at end of file diff --git a/.gitignore b/.gitignore index a39b23fe..7f8f675b 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,6 @@ node_modules deployment *.egg-info *.idea +/build +skaffold.yaml +.tox \ No newline at end of file diff --git a/README.md b/README.md index 4e51ca9b..ac3a5b19 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,6 @@ CloudHarness provides the following command line tools to help application scaff * `harness-deployment` - generate the helm chart to deploy on Kubernetes. * `harness-application` - create a new CloudHarness REST application. -* `harness-codefresh` - generate the Codefresh continuous deployment specification. * `harness-generate` - generates server and client code for all CloudHarness REST applications. @@ -46,8 +45,7 @@ pip install -r requirements.txt ``` ### Generate deployment -To generate a deployment, run either `harness-deployment` or `harness-codefresh` depending on the type of deployment you -like. See [below](#Deployment) to know more. +To generate a deployment, run `harness-deployment`. See [below](#Deployment) to know more. ### Create new REST application To create a new REST application, run `harness-application` from the root. @@ -67,22 +65,22 @@ or simply copy the *blueprint* folder ## Deployment - - ### Manually deploy on a kube cluster The Kubernetes client `kubectl` must be set up and working on the local machine, for instance with a Google Cloud cluster or a local Minikube. -1. Locally build the images with `harness-deployment -b -l +1. Locally build the images with `harness-deployment . -b -l [--registry localhost:5000] [--tag 0.0.1]` 1. Create the namespace `kubectl create ns ch` 1. Create the namespace `kubectl create ns argo-workflows` -1. (Optional) Try the helm chart with `helm install helm --name ch --namespace ch --dry-run` -1. Install the helm chart with `helm install --name=ch deployment/helm --namespace ch` (`helm install ch helm --namespace ch` on helm 3) -1. Install Argo (see below) +1. (Optional) Try the helm chart with `helm install ch deployment/helm -n ch --dry-run` +1. Install or upgrade the helm chart with `helm install ch deployment/helm -n ch --dependency-update` on helm 3) To upgrade an already existing chart, run -`helm upgrade ch deployment/helm --namespace ch --install --force --reset-values` +`helm upgrade ch deployment/helm -n ch --install --reset-values` + + +Can also use Skaffold for local build and deploy (see [here](#skaffold)). ### Continuous deployment with Codefresh The codefresh pipeline setup is provided in `codefresh/codefresh.yaml`. @@ -92,7 +90,7 @@ To setup a new pipeline, simply indicate the remote yaml path `deployment/codefr In order to update the deployment, run ``` -harness-codefresh . +harness-deployment . ``` More information about how to run the script below @@ -125,23 +123,6 @@ On minikube can use the registry addon: Then forward with: `kubectl port-forward --namespace kube-system $(kubectl get po -n kube-system | grep registry | grep -v proxy | \awk '{print $1;}') 5000:5000` -### Argo installation - -Argo is not yet part of the helm chart - -In order to install it in the cluster, run - -``` -kubectl create ns argo -kubectl apply -n argo -f https://raw.githubusercontent.com/argoproj/argo/v2.4.3/manifests/install.yaml -kubectl apply -f argo/argo-service-account.yaml -n argo-workflows -kubectl create rolebinding argo-workflows --clusterrole=admin --serviceaccount=argo-workflows:argo-workflows -n argo-workflows -``` - -See also https://argoproj.github.io/docs/argo/demo.html#2-install-the-controller-and-ui - - - ### Details about deployment generation The following deployment files are generated by `harness-deployment`: @@ -149,7 +130,7 @@ The following deployment files are generated by `harness-deployment`: - Helm chart configuration for custom deployment: **./helm/values.yaml** - Codefresh build and deploment definition: **./codefresh/codefresh.yaml** -The script `harness-codefresh` generates a build script to be used by codefresh. +The script `harness-deployment` also generates a build script to be used by codefresh. The control on the content of those files can be achieved primarily by setting up a custom `values.yaml` and deploy/templates in the application folder. @@ -229,13 +210,21 @@ The script `harness-deployment` allows to optionally build the application's Docker images. Those Docker images are needed if we plan to deploy outside Codefresh, for instance for local testing with Minikube. -#### How to build +#### Direct build with Docker -Run `harness-deployment -b -l` (all images are built unless `-i` option is provided). +Run `harness-deployment . -b -l` (all images are built unless `-i` option is provided). For further information, run `harness-deployment --help` +#### Skaffold dev build and deploy + +[Skaffold](https://skaffold.dev/) configuration is generated by `harness-deployment`. + +Can build and deploy with Skaffold with: + +`skaffold dev --namespace=[NAMESPACE]` (local minikube) +`skaffold dev --namespace=[NAMESPACE] --default-repo=[DOCKER_REGISTRY]` (external cluster or forwarded minikube) #### Build conventions @@ -264,3 +253,4 @@ A CloudHarness application can specify a Kubernetes deployment also using extern Create a new CloudHarness application with the helm templates inside the *deploy* subdirectory +[![Codefresh build status]( https://g.codefresh.io/api/badges/pipeline/tarelli/Cloudharness%2Funittests?type=cf-1&key=eyJhbGciOiJIUzI1NiJ9.NWFkNzMyNDIzNjQ1YWMwMDAxMTJkN2Rl.-gUEkJxH6NCCIRgSIgEikVDte-Q0BsGZKEs4uahgpzs)]( https://g.codefresh.io/pipelines/edit/new/builds?id=6034cfce1036693697cd602b&pipeline=unittests&projects=Cloudharness&projectId=6034cfb83bb11c399e85c71b) \ No newline at end of file diff --git a/applications/accounts/Dockerfile b/applications/accounts/Dockerfile index ab9ddca6..75d1f361 100644 --- a/applications/accounts/Dockerfile +++ b/applications/accounts/Dockerfile @@ -1,3 +1,3 @@ -FROM quay.io/keycloak/keycloak:9.0.2 +FROM quay.io/keycloak/keycloak:11.0.2 # Customize keycloak look COPY themes/custom /opt/jboss/keycloak/themes/custom \ No newline at end of file diff --git a/applications/accounts/deploy/resources/realm.json b/applications/accounts/deploy/resources/realm.json index 1ef6dc59..b7d9e706 100644 --- a/applications/accounts/deploy/resources/realm.json +++ b/applications/accounts/deploy/resources/realm.json @@ -2,7 +2,7 @@ "id": {{ .Values.namespace | quote }}, "realm": {{ .Values.namespace | quote }}, "enabled": true, - "sslRequired": "external", + "sslRequired": {{ ternary "none" "external" (not .Values.tls) | quote }}, "loginTheme": "keycloak", "accountTheme": "keycloak", "adminTheme": "keycloak", diff --git a/applications/accounts/deploy/templates/configmap.yaml b/applications/accounts/deploy/templates/configmap.yaml deleted file mode 100644 index de79112e..00000000 --- a/applications/accounts/deploy/templates/configmap.yaml +++ /dev/null @@ -1,11 +0,0 @@ -{{- /* Be careful with json typos here, mainly trailing ',' */}} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ .Values.apps.accounts.name | quote }} - labels: - app: {{ .Values.apps.accounts.name | quote }} -{{ include "deploy_utils.labels" $ | indent 4 }} -data: - realm.json: {{ tpl (.Files.Get "resources/accounts/realm.json") . | quote }} - diff --git a/applications/accounts/deploy/templates/keycloak-postgres.yaml b/applications/accounts/deploy/templates/keycloak-postgres.yaml deleted file mode 100644 index 0995b5c6..00000000 --- a/applications/accounts/deploy/templates/keycloak-postgres.yaml +++ /dev/null @@ -1,77 +0,0 @@ -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: accounts-db - labels: - app: {{ .Values.apps.accounts.db.name }} -{{ include "deploy_utils.labels" $ | indent 4 }} -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 2Gi ---- -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.apps.accounts.db.name }} - labels: - app: {{ .Values.apps.accounts.db.name }} -{{ include "deploy_utils.labels" $ | indent 4 }} -spec: - type: ClusterIP - ports: - - port: 5432 - selector: - app: {{ .Values.apps.accounts.db.name }} ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ .Values.apps.accounts.db.name }} - labels: - app: {{ .Values.apps.accounts.db.name }} -{{ include "deploy_utils.labels" $ | indent 4 }} -spec: - replicas: 1 - selector: - matchLabels: - app: {{ .Values.apps.accounts.db.name | quote }} -{{ include "deploy_utils.labels" $ | indent 6 }} - template: - metadata: - labels: - app: {{ .Values.apps.accounts.db.name }} -{{ include "deploy_utils.labels" $ | indent 8 }} - spec: - containers: - - name: {{ .Values.apps.accounts.db.name | default "keycloak-postgress" | quote }} - image: {{ .Values.apps.accounts.db.image }} - imagePullPolicy: "IfNotPresent" - env: - - name: POSTGRES_DB - value: {{ .Values.apps.accounts.db.initialdb | quote }} - - name: POSTGRES_USER - value: {{ .Values.apps.accounts.db.user | quote }} - - name: POSTGRES_PASSWORD - value: {{ .Values.apps.accounts.db.pass | quote }} - - name: PGDATA - value: /var/lib/postgresql/data/pgdata - ports: - - containerPort: 5432 - resources: - requests: - memory: "64Mi" - cpu: "100m" - limits: - memory: "128Mi" - cpu: "200m" - volumeMounts: - - name: accounts-db - mountPath: /var/lib/postgresql/data - volumes: - - name: accounts-db - persistentVolumeClaim: - claimName: accounts-db ---- \ No newline at end of file diff --git a/applications/accounts/deploy/templates/keycloak.yaml b/applications/accounts/deploy/templates/keycloak.yaml deleted file mode 100644 index 29fa128e..00000000 --- a/applications/accounts/deploy/templates/keycloak.yaml +++ /dev/null @@ -1,78 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ .Values.apps.accounts.name | quote }} - labels: - app: {{ .Values.apps.accounts.name | quote }} -{{ include "deploy_utils.labels" $ | indent 4 }} -spec: - replicas: 1 - selector: - matchLabels: - app: {{ .Values.apps.accounts.name | quote }} -{{ include "deploy_utils.labels" $ | indent 6 }} - template: - metadata: - {{- if .Values.apps.accounts.harvest }} - annotations: - co.elastic.logs/enabled: "true" - metricbeat: "true" - {{- end }} - labels: - app: {{ .Values.apps.accounts.name | quote }} -{{ include "deploy_utils.labels" $ | indent 8 }} - spec: - {{ if .Values.codefresh }} - imagePullSecrets: - - name: {{ .Values.codefresh.secret }} - {{- end }} - containers: - - name: {{ .Values.apps.accounts.name | default "keycloak" | quote }} - image: {{ .Values.apps.accounts.image }} - imagePullPolicy: {{ include "deploy_utils.pullpolicy" . }} - env: - - name: KEYCLOAK_IMPORT - value: "/tmp/realm.json" - - name: KEYCLOAK_USER - value: {{ .Values.apps.accounts.admin.user | quote }} - - name: KEYCLOAK_PASSWORD - value: {{ .Values.apps.accounts.admin.pass | quote }} - - name: PROXY_ADDRESS_FORWARDING - value: "true" - - name: DB_VENDOR - value: POSTGRES - - name: DB_ADDR - value: {{ .Values.apps.accounts.db.name | quote }} - - name: DB_DATABASE - value: {{ .Values.apps.accounts.db.initialdb | quote }} - - name: DB_USER - value: {{ .Values.apps.accounts.db.user | quote }} - - name: DB_PASSWORD - value: {{ .Values.apps.accounts.db.pass | quote }} - {{- include "deploy_utils.env" . | nindent 8 }} - {{- include "deploy_utils.privenv" . | nindent 8 }} - volumeMounts: - - name: realm-config - mountPath: "/tmp/realm.json" - subPath: realm.json - ports: - - name: http - containerPort: {{ .Values.apps.accounts.port | default 8080 }} - - name: https - containerPort: 8443 - readinessProbe: - httpGet: - path: /auth/realms/master - port: {{ .Values.apps.accounts.port }} - resources: - requests: - memory: "256Mi" - cpu: "200m" - limits: - memory: "1024Mi" - cpu: "500m" - volumes: - - name: realm-config - configMap: - name: {{ .Values.apps.accounts.name | quote }} ---- \ No newline at end of file diff --git a/applications/accounts/deploy/values.yaml b/applications/accounts/deploy/values.yaml index e4622bb3..56fe2027 100644 --- a/applications/accounts/deploy/values.yaml +++ b/applications/accounts/deploy/values.yaml @@ -1,24 +1,68 @@ -admin: - pass: metacell - user: admin - role: administrator +# Deployment & Database +harness: + subdomain: accounts + secured: false + deployment: + auto: true + port: 8080 + resources: + requests: + memory: "512Mi" + cpu: "10m" + limits: + memory: "1024Mi" + cpu: "500m" + service: + auto: true + port: 8080 + env: + - name: KEYCLOAK_IMPORT + value: "/tmp/realm.json" + - name: KEYCLOAK_USER + value: "admin" + - name: KEYCLOAK_PASSWORD + value: "metacell" + - name: PROXY_ADDRESS_FORWARDING + value: "true" + - name: DB_VENDOR + value: "POSTGRES" + - name: DB_ADDR + value: "keycloak-postgres" + - name: DB_DATABASE + value: "auth_db" + - name: DB_USER + value: "user" + - name: DB_PASSWORD + value: "password" + - name: JAVA_OPTS + value: -server -Xms64m -Xmx896m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m -Djava.net.preferIPv4Stack=true -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.awt.headless=true --add-exports=java.base/sun.nio.ch=ALL-UNNAMED --add-exports=jdk.unsupported/sun.misc=ALL-UNNAMED --add-exports=jdk.unsupported/sun.reflect=ALL-UNNAMED + database: + auto: true + name: keycloak-postgres + type: postgres + size: 2Gi + postgres: + image: postgres:10.4 + initialdb: auth_db + user: user + pass: password + resources: + - name: realm-config + src: realm.json + dst: /tmp/realm.json + readinessProbe: + path: /auth/realms/master + +# Keycloak realm configuration client: id: rest-client secret: 5678eb6e-9e2c-4ee5-bd54-34e7411339e8 -db: - image: postgres:10.4 - initialdb: auth_db - name: keycloak-postgress - pass: password - user: user -enabled: true -harvest: true webclient: id: web-client secret: 452952ae-922c-4766-b912-7b106271e34b -name: accounts -port: 8080 -subdomain: accounts -# only use in minikube (with letsencrypt, we use default image) -gatekeeper: - image: accounts-keycloak-gatekeeper \ No newline at end of file +enabled: true +harvest: true +admin: + pass: metacell + user: admin + role: administrator diff --git a/applications/argo/deploy/README.md b/applications/argo/deploy/README.md new file mode 100644 index 00000000..98c1a7e1 --- /dev/null +++ b/applications/argo/deploy/README.md @@ -0,0 +1,13 @@ +# Argo sub chart + +TODO change this to a chart dependency whenever this is fixed: https://github.com/argoproj/argo-helm/issues/521 + +To use as add dependency, add the following to Chart.yaml +``` +dependencies: +- name: argo + version: ">=0.14.0" + repository: https://argoproj.github.io/argo-helm + condition: true + alias: apps-argo +``` diff --git a/applications/argo/deploy/charts/.helmignore b/applications/argo/deploy/charts/.helmignore new file mode 100755 index 00000000..f0c13194 --- /dev/null +++ b/applications/argo/deploy/charts/.helmignore @@ -0,0 +1,21 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj diff --git a/applications/argo/deploy/charts/Chart.yaml b/applications/argo/deploy/charts/Chart.yaml new file mode 100755 index 00000000..9ba00427 --- /dev/null +++ b/applications/argo/deploy/charts/Chart.yaml @@ -0,0 +1,12 @@ +apiVersion: v2 +appVersion: v2.11.7 +description: A Helm chart for Argo Workflows +home: https://github.com/argoproj/argo-helm +icon: https://raw.githubusercontent.com/argoproj/argo/master/docs/assets/argo.png +maintainers: +- name: alexec +- name: alexmt +- name: jessesuen +- name: benjaminws +name: argo +version: 0.14.0 diff --git a/applications/argo/deploy/charts/README.md b/applications/argo/deploy/charts/README.md new file mode 100755 index 00000000..348a0e0a --- /dev/null +++ b/applications/argo/deploy/charts/README.md @@ -0,0 +1,27 @@ +## Argo Workflows Chart + +This is a **community maintained** chart. It is used to set up argo and it's needed dependencies through one command. This is used in conjunction with [helm](https://github.com/kubernetes/helm). + +If you want your deployment of this helm chart to most closely match the [argo CLI](https://github.com/argoproj/argo), you should deploy it in the `kube-system` namespace. + +## Pre-Requisites +This chart uses an install hook to configure the CRD definition. Installation of CRDs is a somewhat privileged process in itself and in RBAC enabled clusters the `default` service account for namespaces does not typically have the ability to do create these. + +A few options are: +- Setup the CRD yourself manually and use `--set installCRD=false` when installing the helm chart. Find the CRDs in the [argo codebase](https://raw.githubusercontent.com/argoproj/argo/master/manifests/base/crds/workflow-crd.yaml) +- Manually create a ServiceAccount in the Namespace which your release will be deployed w/ appropriate bindings to perform this action and set the `init.serviceAccount` attribute +- Augment the `default` ServiceAccount permissions in the Namespace in which your Release is deployed to have the appropriate permissions + +## Usage Notes: +This chart defaults to setting the `controller.instanceID.enabled` to `false` now, which means the deployed controller will act upon any workflow deployed to the cluster. If you would like to limit the behavior and deploy multiple workflow controllers, please use the `controller.instanceID.enabled` attribute along with one of it's configuration options to set the `instanceID` of the workflow controller to be properly scoped for your needs. + +## Values + +The `values.yaml` contains items used to tweak a deployment of this chart. +Fields to note: +* `controller.instanceID.enabled`: If set to true, the Argo Controller will **ONLY** monitor Workflow submissions with a `--instanceid` attribute +* `controller.instanceID.useReleaseName`: If set to true then chart set controller instance id to release name +* `controller.instanceID.explicitID`: Allows customization of an instance id for the workflow controller to monitor +* `controller.workflowNamespaces`: This is a list of namespaces where workflows will be ran +* `minio.install`: If this is true, we'll install [minio](https://github.com/kubernetes/charts/tree/master/stable/minio) and build out the artifactRepository section in workflow controller config map. +* `artifactRepository.s3.accessKeySecret` and `artifactRepository.s3.secretKeySecret` These by default link to minio default credentials stored in the secret deployed by the minio chart. diff --git a/applications/argo/deploy/charts/crds/cluster-workflow-template-crd.yaml b/applications/argo/deploy/charts/crds/cluster-workflow-template-crd.yaml new file mode 100644 index 00000000..a189f17c --- /dev/null +++ b/applications/argo/deploy/charts/crds/cluster-workflow-template-crd.yaml @@ -0,0 +1,23 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: clusterworkflowtemplates.argoproj.io + annotations: + helm.sh/hook: crd-install + helm.sh/hook-delete-policy: before-hook-creation +spec: + group: argoproj.io + version: v1alpha1 + scope: Cluster + names: + kind: ClusterWorkflowTemplate + listKind: ClusterWorkflowTemplateList + plural: clusterworkflowtemplates + shortNames: + - clusterwftmpl + - cwft + singular: clusterworkflowtemplate + versions: + - name: v1alpha1 + served: true + storage: true diff --git a/applications/argo/deploy/charts/crds/cron-workflow-crd.yaml b/applications/argo/deploy/charts/crds/cron-workflow-crd.yaml new file mode 100644 index 00000000..abd50b30 --- /dev/null +++ b/applications/argo/deploy/charts/crds/cron-workflow-crd.yaml @@ -0,0 +1,23 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: cronworkflows.argoproj.io + annotations: + helm.sh/hook: crd-install + helm.sh/hook-delete-policy: before-hook-creation +spec: + group: argoproj.io + names: + kind: CronWorkflow + listKind: CronWorkflowList + plural: cronworkflows + shortNames: + - cwf + - cronwf + singular: cronworkflow + scope: Namespaced + version: v1alpha1 + versions: + - name: v1alpha1 + served: true + storage: true diff --git a/applications/argo/deploy/charts/crds/workflow-crd.yaml b/applications/argo/deploy/charts/crds/workflow-crd.yaml new file mode 100644 index 00000000..24f6abc2 --- /dev/null +++ b/applications/argo/deploy/charts/crds/workflow-crd.yaml @@ -0,0 +1,33 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: workflows.argoproj.io + annotations: + helm.sh/hook: crd-install + helm.sh/hook-delete-policy: before-hook-creation +spec: + additionalPrinterColumns: + - JSONPath: .status.phase + description: Status of the workflow + name: Status + type: string + - JSONPath: .status.startedAt + description: When the workflow was started + format: date-time + name: Age + type: date + group: argoproj.io + names: + kind: Workflow + listKind: WorkflowList + plural: workflows + shortNames: + - wf + singular: workflow + scope: Namespaced + subresources: {} + version: v1alpha1 + versions: + - name: v1alpha1 + served: true + storage: true diff --git a/applications/argo/deploy/charts/crds/workflow-eventbinding-crd.yaml b/applications/argo/deploy/charts/crds/workflow-eventbinding-crd.yaml new file mode 100644 index 00000000..a58de8e7 --- /dev/null +++ b/applications/argo/deploy/charts/crds/workflow-eventbinding-crd.yaml @@ -0,0 +1,19 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: workfloweventbindings.argoproj.io +spec: + group: argoproj.io + names: + kind: WorkflowEventBinding + listKind: WorkflowEventBindingList + plural: workfloweventbindings + shortNames: + - wfeb + singular: workfloweventbinding + scope: Namespaced + version: v1alpha1 + versions: + - name: v1alpha1 + served: true + storage: true diff --git a/applications/argo/deploy/charts/crds/workflow-template-crd.yaml b/applications/argo/deploy/charts/crds/workflow-template-crd.yaml new file mode 100644 index 00000000..0be13451 --- /dev/null +++ b/applications/argo/deploy/charts/crds/workflow-template-crd.yaml @@ -0,0 +1,22 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: workflowtemplates.argoproj.io + annotations: + helm.sh/hook: crd-install + helm.sh/hook-delete-policy: before-hook-creation +spec: + group: argoproj.io + version: v1alpha1 + scope: Namespaced + names: + kind: WorkflowTemplate + listKind: WorkflowTemplateList + plural: workflowtemplates + shortNames: + - wftmpl + singular: workflowtemplate + versions: + - name: v1alpha1 + served: true + storage: true diff --git a/applications/argo/deploy/charts/templates/NOTES.txt b/applications/argo/deploy/charts/templates/NOTES.txt new file mode 100644 index 00000000..a9a5372a --- /dev/null +++ b/applications/argo/deploy/charts/templates/NOTES.txt @@ -0,0 +1,16 @@ +1. Get Argo Server external IP/domain by running: + +kubectl --namespace {{ .Release.Namespace }} get services -o wide | grep argo-{{ .Values.server.name }} + +2. Submit the hello-world workflow by running: + +argo submit https://raw.githubusercontent.com/argoproj/argo/master/examples/hello-world.yaml --watch + +{{ if .Values.minio.install }} + +3. Access Minio UI and create bucket '{{ .Values.minio.defaultBucket.name }}'. Minio UI is available on port 9000 and available via external URL. URL might be retrieved using following +command: + +kubectl --namespace {{ .Release.Namespace }} get services -o wide | grep argo-minio-svc + +{{ end }} diff --git a/applications/argo/deploy/charts/templates/_helpers.tpl b/applications/argo/deploy/charts/templates/_helpers.tpl new file mode 100644 index 00000000..f0d83d2e --- /dev/null +++ b/applications/argo/deploy/charts/templates/_helpers.tpl @@ -0,0 +1,16 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "fullname" -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} diff --git a/applications/argo/deploy/charts/templates/cluster-workflow-template-crd.yaml b/applications/argo/deploy/charts/templates/cluster-workflow-template-crd.yaml new file mode 100644 index 00000000..c9c1cb52 --- /dev/null +++ b/applications/argo/deploy/charts/templates/cluster-workflow-template-crd.yaml @@ -0,0 +1,19 @@ +{{- if .Values.installCRD }} +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: clusterworkflowtemplates.argoproj.io + annotations: + helm.sh/hook: crd-install + helm.sh/hook-delete-policy: before-hook-creation +spec: + group: argoproj.io + version: v1alpha1 + scope: Cluster + names: + kind: ClusterWorkflowTemplate + plural: clusterworkflowtemplates + shortNames: + - clusterwftmpl + - cwft +{{- end }} diff --git a/applications/argo/deploy/charts/templates/cron-workflow-crd.yaml b/applications/argo/deploy/charts/templates/cron-workflow-crd.yaml new file mode 100644 index 00000000..8bf36ab3 --- /dev/null +++ b/applications/argo/deploy/charts/templates/cron-workflow-crd.yaml @@ -0,0 +1,19 @@ +{{- if .Values.installCRD }} +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: cronworkflows.argoproj.io + annotations: + helm.sh/hook: crd-install + helm.sh/hook-delete-policy: before-hook-creation +spec: + group: argoproj.io + names: + kind: CronWorkflow + plural: cronworkflows + shortNames: + - cronwf + - cwf + scope: Namespaced + version: v1alpha1 +{{- end }} \ No newline at end of file diff --git a/applications/argo/deploy/charts/templates/server-cluster-roles.yaml b/applications/argo/deploy/charts/templates/server-cluster-roles.yaml new file mode 100644 index 00000000..0df230a6 --- /dev/null +++ b/applications/argo/deploy/charts/templates/server-cluster-roles.yaml @@ -0,0 +1,102 @@ +{{- if .Values.server.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ .Release.Namespace }}-argo-{{ .Values.server.name }} +rules: +- apiGroups: + - "" + resources: + - configmaps + - events + verbs: + - get + - watch + - list +- apiGroups: + - "" + resources: + - pods + - pods/exec + - pods/log + verbs: + - get + - list + - watch + - delete +- apiGroups: + - "" + resources: + - serviceaccounts + verbs: + - get +- apiGroups: + - "" + resources: + - secrets + verbs: + - get +{{- with .Values.server.rbac.secretWhitelist }} + resourceNames: {{- toYaml . | nindent 4 }} +{{- end }} +- apiGroups: + - "" + resources: + - events + verbs: + - watch +{{- if .Values.controller.persistence }} +- apiGroups: + - "" + resources: + - secrets + resourceNames: + {{- with .Values.controller.persistence.postgresql }} + - {{ .userNameSecret.name }} + - {{ .passwordSecret.name }} + {{- end}} + {{- with .Values.controller.persistence.mysql }} + - {{ .userNameSecret.name }} + - {{ .passwordSecret.name }} + {{- end}} + verbs: + - get +{{- end}} +- apiGroups: + - argoproj.io + resources: + - workflows + - workfloweventbindings + - workflowtemplates + - cronworkflows + - cronworkflows/finalizers + - clusterworkflowtemplates + verbs: + - create + - get + - list + - watch + - update + - patch + - delete +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ .Release.Namespace }}-argo-{{ .Values.server.name }}-cluster-template +rules: +- apiGroups: + - argoproj.io + resources: + - clusterworkflowtemplates + verbs: + - get + - list + - watch + {{- if .Values.server.clusterWorkflowTemplates.enableEditing }} + - create + - update + - patch + - delete + {{- end }} +{{- end }} diff --git a/applications/argo/deploy/charts/templates/server-crb.yaml b/applications/argo/deploy/charts/templates/server-crb.yaml new file mode 100644 index 00000000..070eb3a2 --- /dev/null +++ b/applications/argo/deploy/charts/templates/server-crb.yaml @@ -0,0 +1,33 @@ +{{- if and .Values.server.enabled .Values.server.createServiceAccount -}} +apiVersion: rbac.authorization.k8s.io/v1 +{{- if .Values.singleNamespace }} +kind: RoleBinding +metadata: + name: argo-{{ .Values.server.name}} +{{ else }} +kind: ClusterRoleBinding +metadata: + name: {{ .Release.Namespace }}-argo-{{ .Values.server.name}} +{{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ .Release.Namespace }}-argo-{{ .Values.server.name}} +subjects: +- kind: ServiceAccount + name: {{ .Values.server.serviceAccount }} + namespace: {{ .Release.Namespace }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ .Release.Namespace }}-argo-{{ .Values.server.name}}-cluster-template +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ .Release.Namespace }}-argo-{{ .Values.server.name}}-cluster-template +subjects: +- kind: ServiceAccount + name: {{ .Values.server.serviceAccount }} + namespace: {{ .Release.Namespace }} +{{- end -}} diff --git a/applications/argo/deploy/charts/templates/server-deployment-pdb.yaml b/applications/argo/deploy/charts/templates/server-deployment-pdb.yaml new file mode 100644 index 00000000..4056399d --- /dev/null +++ b/applications/argo/deploy/charts/templates/server-deployment-pdb.yaml @@ -0,0 +1,25 @@ +{{- if .Values.server.enabled -}} +{{- if .Values.server.pdb.enabled -}} +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: argo-{{ .Values.server.name}} + labels: + app: argo-{{ .Values.server.name}} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +spec: + {{- if .Values.server.pdb.minAvailable }} + minAvailable: {{ .Values.server.pdb.minAvailable }} + {{- else if .Values.server.pdb.maxUnavailable }} + maxUnavailable: {{ .Values.server.pdb.maxUnavailable }} + {{- else }} + minAvailable: 0 + {{- end }} + selector: + matchLabels: + app: argo-{{ .Values.server.name}} + release: {{ .Release.Name }} +{{- end -}} +{{- end -}} diff --git a/applications/argo/deploy/charts/templates/server-deployment.yaml b/applications/argo/deploy/charts/templates/server-deployment.yaml new file mode 100644 index 00000000..ea5893ec --- /dev/null +++ b/applications/argo/deploy/charts/templates/server-deployment.yaml @@ -0,0 +1,108 @@ +{{- if .Values.server.enabled -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: argo-{{ .Values.server.name}} + labels: + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +spec: + replicas: {{ .Values.server.replicas }} + selector: + matchLabels: + app: argo-{{ .Values.server.name}} + release: {{ .Release.Name }} + template: + metadata: + labels: + app: argo-{{ .Values.server.name}} + release: {{ .Release.Name }} + {{- if .Values.server.podLabels }} + {{- toYaml .Values.server.podLabels | nindent 8 }} + {{- end }} + {{- if .Values.server.podAnnotations }} + annotations: +{{ toYaml .Values.server.podAnnotations | indent 8}}{{- end }} + spec: + serviceAccountName: {{ .Values.server.serviceAccount | quote }} + {{- if .Values.server.podSecurityContext }} + securityContext: + {{- toYaml .Values.server.podSecurityContext | nindent 8 }} + {{- end }} + containers: + - name: argo-server + args: + - server + - --configmap=argo-{{ .Values.controller.name }}-configmap + {{- if .Values.server.extraArgs }} + {{- toYaml .Values.server.extraArgs | nindent 10 }} + {{- end }} + {{- if .Values.server.secure }} + - "--secure" + {{- end }} + {{- if .Values.singleNamespace }} + - "--namespaced" + {{- end }} + image: "{{ .Values.images.namespace }}/{{ .Values.images.server }}:{{ default .Values.images.tag .Values.server.image.tag }}" + imagePullPolicy: {{ .Values.images.pullPolicy }} + {{- if .Values.server.podPortName }} + ports: + - name: {{ .Values.server.podPortName }} + containerPort: 2746 + {{- end }} + readinessProbe: + httpGet: + path: / + port: 2746 + {{- if .Values.server.secure }} + scheme: HTTPS + {{- else }} + scheme: HTTP + {{- end }} + initialDelaySeconds: 10 + periodSeconds: 20 + env: + - name: IN_CLUSTER + value: "true" + - name: ARGO_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: BASE_HREF + value: {{ .Values.server.baseHref | quote }} + resources: + {{- toYaml .Values.server.resources | nindent 12 }} + volumeMounts: + - name: tmp + mountPath: /tmp + {{- with .Values.server.volumeMounts }} + {{- toYaml . | nindent 10}} + {{- end }} + {{- with .Values.images.pullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: tmp + emptyDir: {} + {{- with .Values.server.volumes }} + {{- toYaml . | nindent 6}} + {{- end }} + {{- with .Values.server.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.server.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.server.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.server.priorityClassName }} + priorityClassName: {{ .Values.server.priorityClassName }} + {{- end }} +{{- end -}} diff --git a/applications/argo/deploy/charts/templates/server-sa.yaml b/applications/argo/deploy/charts/templates/server-sa.yaml new file mode 100644 index 00000000..5b419a65 --- /dev/null +++ b/applications/argo/deploy/charts/templates/server-sa.yaml @@ -0,0 +1,8 @@ +{{- if and .Values.server.enabled .Values.server.createServiceAccount -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.server.serviceAccount }} + annotations: +{{ toYaml .Values.server.serviceAccountAnnotations | indent 4 }} +{{- end -}} diff --git a/applications/argo/deploy/charts/templates/server-service.yaml b/applications/argo/deploy/charts/templates/server-service.yaml new file mode 100644 index 00000000..e891d785 --- /dev/null +++ b/applications/argo/deploy/charts/templates/server-service.yaml @@ -0,0 +1,33 @@ +{{- if .Values.server.enabled -}} +apiVersion: v1 +kind: Service +metadata: + name: argo-{{ .Values.server.name }} + labels: + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + {{- if .Values.server.serviceLabels }} + {{- toYaml .Values.server.serviceLabels | nindent 4 }} + {{- end }} + {{- if .Values.server.serviceAnnotations }} + annotations: +{{ toYaml .Values.server.serviceAnnotations | indent 4}}{{- end }} +spec: + ports: + - port: {{ .Values.server.servicePort }} + {{- if .Values.server.servicePortName }} + name: {{ .Values.server.servicePortName }} + {{- end }} + targetPort: 2746 + selector: + app: argo-{{ .Values.server.name }} + sessionAffinity: None + type: {{ .Values.server.serviceType }} + {{- if and (eq .Values.server.serviceType "LoadBalancer") .Values.server.loadBalancerIP }} + loadBalancerIP: {{ .Values.server.loadBalancerIP | quote }} + {{- end }} + {{- if and (eq .Values.server.serviceType "LoadBalancer") .Values.server.loadBalancerSourceRanges }} + loadBalancerSourceRanges: +{{ toYaml .Values.server.loadBalancerSourceRanges | indent 4 }}{{- end }} +{{- end -}} diff --git a/applications/argo/deploy/charts/templates/worfkflow-controller-secrets-access.yaml b/applications/argo/deploy/charts/templates/worfkflow-controller-secrets-access.yaml new file mode 100644 index 00000000..bb68e548 --- /dev/null +++ b/applications/argo/deploy/charts/templates/worfkflow-controller-secrets-access.yaml @@ -0,0 +1,18 @@ +{{ if .Values.minio.install }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: argo-{{ .Values.controller.name}}-minio-secret +rules: +- apiGroups: + - "" + resources: + - secrets + resourceNames: + - {{ .Values.artifactRepository.s3.accessKeySecret.name | default (printf "%s-%s" .Release.Name "minio") | quote }} + - {{ .Values.artifactRepository.s3.secretKeySecret.name | default (printf "%s-%s" .Release.Name "minio") | quote }} + verbs: + - get + - watch + - list +{{- end }} \ No newline at end of file diff --git a/applications/argo/deploy/charts/templates/workflow-aggregate-roles.yaml b/applications/argo/deploy/charts/templates/workflow-aggregate-roles.yaml new file mode 100644 index 00000000..b89e7b13 --- /dev/null +++ b/applications/argo/deploy/charts/templates/workflow-aggregate-roles.yaml @@ -0,0 +1,89 @@ +{{- if .Values.createAggregateRoles }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + annotations: + helm.sh/hook: pre-install + helm.sh/hook-delete-policy: before-hook-creation + name: argo-aggregate-to-view + labels: + rbac.authorization.k8s.io/aggregate-to-view: "true" +rules: +- apiGroups: + - argoproj.io + resources: + - workflows + - workflows/finalizers + - workflowtemplates + - workflowtemplates/finalizers + - cronworkflows + - cronworkflows/finalizers + - clusterworkflowtemplates + - clusterworkflowtemplates/finalizers + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + annotations: + helm.sh/hook: pre-install + helm.sh/hook-delete-policy: before-hook-creation + name: argo-aggregate-to-edit + labels: + rbac.authorization.k8s.io/aggregate-to-edit: "true" +rules: +- apiGroups: + - argoproj.io + resources: + - workflows + - workflows/finalizers + - workflowtemplates + - workflowtemplates/finalizers + - cronworkflows + - cronworkflows/finalizers + - clusterworkflowtemplates + - clusterworkflowtemplates/finalizers + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + annotations: + helm.sh/hook: pre-install + helm.sh/hook-delete-policy: before-hook-creation + name: argo-aggregate-to-admin + labels: + rbac.authorization.k8s.io/aggregate-to-admin: "true" +rules: +- apiGroups: + - argoproj.io + resources: + - workflows + - workflows/finalizers + - workflowtemplates + - workflowtemplates/finalizers + - cronworkflows + - cronworkflows/finalizers + - clusterworkflowtemplates + - clusterworkflowtemplates/finalizers + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch +{{- end }} diff --git a/applications/argo/deploy/charts/templates/workflow-controller-cluster-roles.yaml b/applications/argo/deploy/charts/templates/workflow-controller-cluster-roles.yaml new file mode 100644 index 00000000..d2b5c381 --- /dev/null +++ b/applications/argo/deploy/charts/templates/workflow-controller-cluster-roles.yaml @@ -0,0 +1,123 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ .Release.Namespace }}-argo-{{ .Values.controller.name }} +rules: +- apiGroups: + - "" + resources: + - pods + - pods/exec + verbs: + - create + - get + - list + - watch + - update + - patch + - delete +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - watch + - list +- apiGroups: + - "" + resources: + - persistentvolumeclaims + verbs: + - create + - delete +- apiGroups: + - argoproj.io + resources: + - workflows + - workflows/finalizers + verbs: + - get + - list + - watch + - update + - patch + - delete + - create +- apiGroups: + - argoproj.io + resources: + - workflowtemplates + - workflowtemplates/finalizers + - clusterworkflowtemplates + - clusterworkflowtemplates/finalizers + verbs: + - get + - list + - watch +- apiGroups: + - argoproj.io + resources: + - cronworkflows + - cronworkflows/finalizers + verbs: + - get + - list + - watch + - update + - patch + - delete +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +- apiGroups: + - "" + resources: + - serviceaccounts + verbs: + - get + - list +- apiGroups: + - "policy" + resources: + - poddisruptionbudgets + verbs: + - create + - get + - delete +{{- if .Values.controller.persistence }} +- apiGroups: + - "" + resources: + - secrets + resourceNames: + {{- if .Values.controller.persistence.postgresql }} + - {{ .Values.controller.persistence.postgresql.userNameSecret.name }} + - {{ .Values.controller.persistence.postgresql.passwordSecret.name }} + {{- end}} + {{- if .Values.controller.persistence.mysql }} + - {{ .Values.controller.persistence.mysql.userNameSecret.name }} + - {{ .Values.controller.persistence.mysql.passwordSecret.name }} + {{- end}} + verbs: + - get +{{- end}} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ .Release.Namespace }}-argo-{{ .Values.controller.name }}-cluster-template +rules: +- apiGroups: + - argoproj.io + resources: + - clusterworkflowtemplates + - clusterworkflowtemplates/finalizers + verbs: + - get + - list + - watch diff --git a/applications/argo/deploy/charts/templates/workflow-controller-config-map.yaml b/applications/argo/deploy/charts/templates/workflow-controller-config-map.yaml new file mode 100644 index 00000000..18128726 --- /dev/null +++ b/applications/argo/deploy/charts/templates/workflow-controller-config-map.yaml @@ -0,0 +1,89 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: argo-{{ .Values.controller.name }}-configmap + labels: + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +data: + config: | + {{- if .Values.controller.instanceID.enabled }} + {{- if .Values.controller.instanceID.useReleaseName }} + instanceID: {{ .Release.Name }} + {{- else }} + instanceID: {{ .Values.controller.instanceID.explicitID }} + {{- end }} + {{- end }} + containerRuntimeExecutor: {{ .Values.controller.containerRuntimeExecutor }} + {{- if .Values.controller.parallelism }} + parallelism: {{ .Values.controller.parallelism }} + {{- end }} + {{- if or .Values.executor.resources .Values.executor.env .Values.executor.securityContext}} + executor: + {{- with .Values.executor.resources }} + resources: {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.executor.env }} + env: {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.executor.securityContext }} + securityContext: {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + {{- if or .Values.minio.install .Values.useDefaultArtifactRepo }} + artifactRepository: + {{- if .Values.artifactRepository.archiveLogs }} + archiveLogs: {{ .Values.artifactRepository.archiveLogs }} + {{- end }} + {{- if .Values.artifactRepository.gcs }} + gcs: +{{ toYaml .Values.artifactRepository.gcs | indent 8}} + {{- else }} + s3: + {{- if .Values.useStaticCredentials }} + accessKeySecret: + key: {{ .Values.artifactRepository.s3.accessKeySecret.key }} + name: {{ .Values.artifactRepository.s3.accessKeySecret.name | default (printf "%s-%s" .Release.Name "minio") }} + secretKeySecret: + key: {{ .Values.artifactRepository.s3.secretKeySecret.key }} + name: {{ .Values.artifactRepository.s3.secretKeySecret.name | default (printf "%s-%s" .Release.Name "minio") }} + {{- end }} + bucket: {{ .Values.artifactRepository.s3.bucket | default .Values.minio.defaultBucket.name }} + endpoint: {{ .Values.artifactRepository.s3.endpoint | default (printf "%s-%s" .Release.Name "minio:9000") }} + insecure: {{ .Values.artifactRepository.s3.insecure }} + {{- if .Values.artifactRepository.s3.keyFormat }} + keyFormat: {{ .Values.artifactRepository.s3.keyFormat }} + {{- end }} + {{- if .Values.artifactRepository.s3.region }} + region: {{ .Values.artifactRepository.s3.region }} + {{- end }} + {{- if .Values.artifactRepository.s3.roleARN }} + roleARN: {{ .Values.artifactRepository.s3.roleARN }} + {{- end }} + {{- if .Values.artifactRepository.s3.useSDKCreds }} + useSDKCreds: {{ .Values.artifactRepository.s3.useSDKCreds }} + {{- end }} + {{- end }} + {{- end}} + {{- if .Values.controller.metricsConfig.enabled }} + metricsConfig: +{{ toYaml .Values.controller.metricsConfig | indent 6}}{{- end }} + {{- if .Values.controller.telemetryConfig.enabled }} + telemetryConfig: +{{ toYaml .Values.controller.telemetryConfig | indent 6}}{{- end }} + {{- if .Values.controller.persistence }} + persistence: +{{ toYaml .Values.controller.persistence | indent 6 }}{{- end }} + {{- if .Values.controller.workflowDefaults }} + workflowDefaults: +{{ toYaml .Values.controller.workflowDefaults | indent 6 }}{{- end }} + {{- with .Values.server.sso }} + sso: {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.controller.workflowRestrictions }} + workflowRestrictions: {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.controller.links }} + links: {{- toYaml . | nindent 6 }} + {{- end }} diff --git a/applications/argo/deploy/charts/templates/workflow-controller-crb.yaml b/applications/argo/deploy/charts/templates/workflow-controller-crb.yaml new file mode 100644 index 00000000..6bc55ada --- /dev/null +++ b/applications/argo/deploy/charts/templates/workflow-controller-crb.yaml @@ -0,0 +1,40 @@ +apiVersion: rbac.authorization.k8s.io/v1 +{{- if .Values.singleNamespace }} +kind: RoleBinding +{{ else }} +kind: ClusterRoleBinding +{{- end }} +metadata: + name: {{ .Release.Namespace }}-argo-{{ .Values.controller.name }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ .Release.Namespace }}-argo-{{ .Values.controller.name }} +subjects: + - kind: ServiceAccount + name: {{ .Values.controller.serviceAccount }} + namespace: {{ .Release.Namespace }} +{{- if .Values.controller.workflowNamespaces }} +{{- $uiServiceAccount := .Values.controller.serviceAccount }} +{{- $namespace := .Release.Namespace }} +{{- range $key := .Values.controller.workflowNamespaces }} + {{- if not (eq $key $namespace) }} + - kind: ServiceAccount + name: {{ $uiServiceAccount }} + namespace: {{ $key }} + {{- end }} +{{- end }} +{{- end }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ .Release.Namespace }}-argo-{{ .Values.controller.name }}-cluster-template +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ .Release.Namespace }}-argo-{{ .Values.controller.name }}-cluster-template +subjects: + - kind: ServiceAccount + name: {{ .Values.controller.serviceAccount }} + namespace: {{ .Release.Namespace }} diff --git a/applications/argo/deploy/charts/templates/workflow-controller-deployment-pdb.yaml b/applications/argo/deploy/charts/templates/workflow-controller-deployment-pdb.yaml new file mode 100644 index 00000000..7e8da5de --- /dev/null +++ b/applications/argo/deploy/charts/templates/workflow-controller-deployment-pdb.yaml @@ -0,0 +1,23 @@ +{{- if .Values.controller.pdb.enabled }} +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: argo-{{ .Values.controller.name}} + labels: + app: argo-{{ .Values.controller.name}} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +spec: + {{- if .Values.controller.pdb.minAvailable }} + minAvailable: {{ .Values.controller.pdb.minAvailable }} + {{- else if .Values.controller.pdb.maxUnavailable }} + maxUnavailable: {{ .Values.controller.pdb.maxUnavailable }} + {{- else }} + minAvailable: 0 + {{- end }} + selector: + matchLabels: + app: argo-{{ .Values.controller.name}} + release: {{ .Release.Name }} +{{- end }} diff --git a/applications/argo/deploy/charts/templates/workflow-controller-deployment.yaml b/applications/argo/deploy/charts/templates/workflow-controller-deployment.yaml new file mode 100755 index 00000000..68eceb20 --- /dev/null +++ b/applications/argo/deploy/charts/templates/workflow-controller-deployment.yaml @@ -0,0 +1,91 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: argo-{{ .Values.controller.name}} + labels: + app: argo-{{ .Values.controller.name}} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +spec: + replicas: {{ .Values.controller.replicas }} + selector: + matchLabels: + app: argo-{{ .Values.controller.name}} + release: {{ .Release.Name }} + template: + metadata: + labels: + app: argo-{{ .Values.controller.name}} + release: {{ .Release.Name }} + {{- if .Values.controller.podLabels }} + {{ toYaml .Values.controller.podLabels | nindent 8}} + {{- end }} + {{- if .Values.controller.podAnnotations }} + annotations: +{{ toYaml .Values.controller.podAnnotations | indent 8}}{{- end }} + spec: + serviceAccountName: {{ .Values.controller.serviceAccount | quote }} + {{- if .Values.controller.podSecurityContext }} + securityContext: + {{- toYaml .Values.controller.podSecurityContext | nindent 8 }} + {{- end }} + containers: + - name: controller + image: "{{ .Values.images.namespace }}/{{ .Values.images.controller }}:{{ default .Values.images.tag .Values.controller.image.tag }}" + imagePullPolicy: {{ .Values.images.pullPolicy }} + command: [ "workflow-controller" ] + args: + - "--configmap" + - "argo-{{ .Values.controller.name}}-configmap" + - "--executor-image" + - "{{ .Values.images.namespace }}/{{ .Values.images.executor }}:{{ default .Values.images.tag .Values.executor.image.tag }}" + - "--loglevel" + - "{{ .Values.controller.logging.level }}" + - "--gloglevel" + - "{{ .Values.controller.logging.globallevel }}" + {{- if .Values.singleNamespace }} + - "--namespaced" + {{- end }} + {{- with .Values.controller.workflowWorkers }} + - "--workflow-workers" + - {{ . | quote }} + {{- end }} + {{- with .Values.controller.podWorkers }} + - "--pod-workers" + - {{ . | quote }} + {{- end }} + env: + - name: ARGO_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + {{- with .Values.controller.extraEnv }} + {{ toYaml . | nindent 10 }} + {{- end }} + resources: + {{- toYaml .Values.controller.resources | nindent 12 }} + {{- if .Values.controller.metricsConfig.enabled }} + ports: + - containerPort: 8080 + {{- end }} + {{- with .Values.images.pullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.controller.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.controller.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.controller.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.controller.priorityClassName }} + priorityClassName: {{ .Values.controller.priorityClassName }} + {{- end }} diff --git a/applications/argo/deploy/charts/templates/workflow-controller-minio-secret-crb.yaml b/applications/argo/deploy/charts/templates/workflow-controller-minio-secret-crb.yaml new file mode 100644 index 00000000..fd9c73b1 --- /dev/null +++ b/applications/argo/deploy/charts/templates/workflow-controller-minio-secret-crb.yaml @@ -0,0 +1,25 @@ +{{ if .Values.minio.install }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: argo-{{ .Values.controller.name}}-minio-binding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: argo-{{ .Values.controller.name}}-minio-secret +subjects: + - kind: ServiceAccount + name: {{ .Values.controller.serviceAccount }} + namespace: {{ .Release.Namespace }} +{{- if .Values.controller.workflowNamespaces }} +{{- $uiServiceAccount := .Values.controller.serviceAccount }} +{{- $namespace := .Release.Namespace }} +{{- range $key := .Values.controller.workflowNamespaces }} + {{- if not (eq $key $namespace) }} + - kind: ServiceAccount + name: {{ $uiServiceAccount }} + namespace: {{ $key }} + {{- end }} +{{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/applications/argo/deploy/charts/templates/workflow-controller-sa.yaml b/applications/argo/deploy/charts/templates/workflow-controller-sa.yaml new file mode 100644 index 00000000..02d274da --- /dev/null +++ b/applications/argo/deploy/charts/templates/workflow-controller-sa.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.controller.serviceAccount }} + annotations: +{{ toYaml .Values.controller.serviceAccountAnnotations | indent 4 }} diff --git a/applications/argo/deploy/charts/templates/workflow-controller-service.yaml b/applications/argo/deploy/charts/templates/workflow-controller-service.yaml new file mode 100644 index 00000000..4778e3aa --- /dev/null +++ b/applications/argo/deploy/charts/templates/workflow-controller-service.yaml @@ -0,0 +1,38 @@ +{{- if or .Values.controller.metricsConfig.enabled .Values.controller.telemetryConfig.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: argo-{{ .Values.controller.name }} + labels: + app: argo-{{ .Values.controller.name}} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + {{- if .Values.controller.serviceLabels }} + {{ toYaml .Values.controller.serviceLabels | nindent 4}} + {{- end }} + {{- if .Values.controller.serviceAnnotations }} + annotations: +{{ toYaml .Values.controller.serviceAnnotations | indent 4}}{{- end }} +spec: + ports: + {{- if .Values.controller.metricsConfig.enabled }} + - name: {{ .Values.controller.metricsServicePortName }} + port: {{ .Values.controller.metricsServicePort }} + protocol: TCP + targetPort: {{ .Values.controller.metricsConfig.port }} + {{- end }} + {{- if .Values.controller.telemetryConfig.enabled }} + - name: {{ .Values.controller.telemetryServicePortName }} + port: {{ .Values.controller.telemetryServicePort }} + protocol: TCP + targetPort: {{ .Values.controller.telemetryConfig.port }} + {{- end }} + selector: + app: argo-{{ .Values.controller.name }} + sessionAffinity: None + type: {{ .Values.controller.serviceType }} + {{- if and (eq .Values.controller.serviceType "LoadBalancer") .Values.controller.loadBalancerSourceRanges }} + loadBalancerSourceRanges: +{{ toYaml .Values.controller.loadBalancerSourceRanges | indent 4 }}{{- end }} +{{- end -}} diff --git a/applications/argo/deploy/charts/templates/workflow-controller-servicemonitor.yaml b/applications/argo/deploy/charts/templates/workflow-controller-servicemonitor.yaml new file mode 100644 index 00000000..de851d94 --- /dev/null +++ b/applications/argo/deploy/charts/templates/workflow-controller-servicemonitor.yaml @@ -0,0 +1,33 @@ +{{- if and (or .Values.controller.metricsConfig.enabled .Values.controller.telemetryConfig.enabled) .Values.controller.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: argo-{{ .Values.controller.name }} + labels: + app: argo-{{ .Values.controller.name}} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + {{- if .Values.controller.serviceMonitor.additionalLabels }} +{{ toYaml .Values.controller.serviceMonitor.additionalLabels | indent 4 }} + {{- end }} +spec: + endpoints: + {{- if .Values.controller.metricsConfig.enabled }} + - port: metrics + path: {{ .Values.controller.metricsConfig.path }} + interval: 30s + {{- end }} + {{- if .Values.controller.telemetryConfig.enabled }} + - port: telemetry + path: {{ .Values.controller.telemetryConfig.path }} + interval: 30s + {{- end }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + selector: + matchLabels: + app: argo-{{ .Values.controller.name}} + release: {{ .Release.Name }} +{{- end }} diff --git a/applications/argo/deploy/charts/templates/workflow-crd.yaml b/applications/argo/deploy/charts/templates/workflow-crd.yaml new file mode 100644 index 00000000..dca2e1bc --- /dev/null +++ b/applications/argo/deploy/charts/templates/workflow-crd.yaml @@ -0,0 +1,28 @@ +{{- if .Values.installCRD }} +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: workflows.argoproj.io + annotations: + helm.sh/hook: crd-install + helm.sh/hook-delete-policy: before-hook-creation +spec: + additionalPrinterColumns: + - JSONPath: .status.phase + description: Status of the workflow + name: Status + type: string + - JSONPath: .status.startedAt + description: When the workflow was started + format: date-time + name: Age + type: date + group: argoproj.io + names: + kind: Workflow + plural: workflows + shortNames: + - wf + scope: Namespaced + version: v1alpha1 +{{- end }} diff --git a/applications/argo/deploy/charts/templates/workflow-rb.yaml b/applications/argo/deploy/charts/templates/workflow-rb.yaml new file mode 100644 index 00000000..5af225db --- /dev/null +++ b/applications/argo/deploy/charts/templates/workflow-rb.yaml @@ -0,0 +1,19 @@ +{{- if .Values.workflow.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: argo-workflow +{{- if .Values.workflow.namespace }} + namespace: {{ .Values.workflow.namespace }} +{{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: argo-workflow +subjects: +- kind: ServiceAccount + name: {{ .Values.workflow.serviceAccount.name }} + {{- if .Values.workflow.namespace }} + namespace: {{ .Values.workflow.namespace }} + {{- end }} +{{- end }} diff --git a/applications/argo/deploy/charts/templates/workflow-role.yaml b/applications/argo/deploy/charts/templates/workflow-role.yaml new file mode 100644 index 00000000..7b4b7275 --- /dev/null +++ b/applications/argo/deploy/charts/templates/workflow-role.yaml @@ -0,0 +1,25 @@ +{{- if .Values.workflow.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: argo-workflow + {{- if .Values.workflow.namespace }} + namespace: {{ .Values.workflow.namespace }} + {{- end }} +rules: +- apiGroups: + - "" + resources: + - pods + verbs: + - get + - watch + - patch +- apiGroups: + - "" + resources: + - pods/log + verbs: + - get + - watch +{{- end }} diff --git a/applications/argo/deploy/charts/templates/workflow-sa.yaml b/applications/argo/deploy/charts/templates/workflow-sa.yaml new file mode 100644 index 00000000..45d97cf0 --- /dev/null +++ b/applications/argo/deploy/charts/templates/workflow-sa.yaml @@ -0,0 +1,13 @@ +{{- if .Values.workflow.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.workflow.serviceAccount.name }} + {{- if .Values.workflow.namespace }} + namespace: {{ .Values.workflow.namespace }} + {{- end }} + {{- with .Values.workflow.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/applications/argo/deploy/charts/templates/workflow-template-crd.yaml b/applications/argo/deploy/charts/templates/workflow-template-crd.yaml new file mode 100644 index 00000000..55c940d5 --- /dev/null +++ b/applications/argo/deploy/charts/templates/workflow-template-crd.yaml @@ -0,0 +1,18 @@ +{{- if .Values.installCRD }} +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: workflowtemplates.argoproj.io + annotations: + helm.sh/hook: crd-install + helm.sh/hook-delete-policy: before-hook-creation +spec: + group: argoproj.io + version: v1alpha1 + scope: Namespaced + names: + kind: WorkflowTemplate + plural: workflowtemplates + shortNames: + - wftmpl +{{- end }} diff --git a/applications/argo/deploy/charts/values.yaml b/applications/argo/deploy/charts/values.yaml new file mode 100755 index 00000000..d60e5195 --- /dev/null +++ b/applications/argo/deploy/charts/values.yaml @@ -0,0 +1,314 @@ +images: + namespace: argoproj + controller: workflow-controller + server: argocli + executor: argoexec + pullPolicy: Always + # Secrets with credentials to pull images from a private registry + pullSecrets: [] + # - name: argo-pull-secret + tag: v2.12.3 + +crdVersion: v1alpha1 +installCRD: true + +init: + # By default the installation will not set an explicit one, which will mean it uses `default` for the namespace the chart is + # being deployed to. In RBAC clusters, that will almost certainly fail. See the NOTES: section of the readme for more info. + serviceAccount: "" + +createAggregateRoles: true + +# Restrict Argo to only deploy into a single namespace by apply Roles and RoleBindings instead of the Cluster equivalents, +# and start argo-cli with the --namespaced flag. Use it in clusters with strict access policy. +singleNamespace: false + +workflow: + namespace: "" # Specify namespace if workflows run in another namespace than argo. This controls where the service account and RBAC resources will be created. + serviceAccount: + create: false # Specifies whether a service account should be created + annotations: {} + name: "argo-workflow" # Service account which is used to run workflows + rbac: + create: true # adds Role and RoleBinding for the above specified service account to be able to run workflows + +controller: + image: + # Overrides .images.tag if defined. + tag: "" + # parallelism dictates how many workflows can be running at the same time + parallelism: + # podAnnotations is an optional map of annotations to be applied to the controller Pods + podAnnotations: {} + # Optional labels to add to the controller pods + podLabels: {} + # SecurityContext to set on the controller pods + podSecurityContext: {} + # podPortName: http + metricsConfig: + enabled: false + path: /metrics + port: 8080 + persistence: {} + # connectionPool: + # maxIdleConns: 100 + # maxOpenConns: 0 + # # save the entire workflow into etcd and DB + # nodeStatusOffLoad: false + # # enable archiving of old workflows + # archive: false + # postgresql: + # host: localhost + # port: 5432 + # database: postgres + # tableName: argo_workflows + # # the database secrets must be in the same namespace of the controller + # userNameSecret: + # name: argo-postgres-config + # key: username + # passwordSecret: + # name: argo-postgres-config + # key: password + workflowDefaults: {} # Only valid for 2.7+ + # spec: + # ttlStrategy: + # secondsAfterCompletion: 84600 + # workflowWorkers: 32 + # podWorkers: 32 + workflowRestrictions: {} # Only valid for 2.9+ + # templateReferencing: Strict|Secure + telemetryConfig: + enabled: false + path: /telemetry + port: 8081 + serviceMonitor: + enabled: false + additionalLabels: {} + serviceAccount: argo + # Service account annotations + serviceAccountAnnotations: {} + name: workflow-controller + workflowNamespaces: + - default + containerRuntimeExecutor: docker + instanceID: + # `instanceID.enabled` configures the controller to filter workflow submissions + # to only those which have a matching instanceID attribute. + enabled: true + # NOTE: If `instanceID.enabled` is set to `true` then either `instanceID.userReleaseName` + # or `instanceID.explicitID` must be defined. + useReleaseName: true + # explicitID: unique-argo-controller-identifier + logging: + level: info + globallevel: "0" + serviceType: ClusterIP + metricsServicePort: 8080 + metricsServicePortName: metrics + telemetryServicePort: 8081 + telemetryServicePortName: telemetry + # Annotations to be applied to the controller Service + serviceAnnotations: {} + # Optional labels to add to the controller Service + serviceLabels: {} + # Source ranges to allow access to service from. Only applies to + # service type `LoadBalancer` + loadBalancerSourceRanges: [] + resources: {} + # The list of environment variable definitions to be added to the controller + # manages container verbatim. + extraEnv: [] + replicas: 1 + pdb: + enabled: false + # minAvailable: 1 + # maxUnavailable: 1 + ## Node selectors and tolerations for server scheduling to nodes with taints + ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + ## + nodeSelector: + kubernetes.io/os: linux + tolerations: [] + affinity: {} + # Leverage a PriorityClass to ensure your pods survive resource shortages + # ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ + # PriorityClass: system-cluster-critical + priorityClassName: "" + # https://argoproj.github.io/argo/links/ + links: [] + +# executor controls how the init and wait container should be customized +executor: + image: + # Overrides .images.tag if defined. + tag: "" + resources: {} + # Adds environment variables for the executor. + env: {} + # sets security context for the executor container + securityContext: {} + +server: + enabled: true + # only updates base url of resources on client side, + # it's expected that a proxy server rewrites the request URL and gets rid of this prefix + # https://github.com/argoproj/argo/issues/716#issuecomment-433213190 + baseHref: / + image: + # Overrides .images.tag if defined. + tag: "" + # optional map of annotations to be applied to the ui Pods + podAnnotations: {} + # Optional labels to add to the UI pods + podLabels: {} + # SecurityContext to set on the server pods + podSecurityContext: {} + name: server + serviceType: ClusterIP + servicePort: 2746 + # servicePortName: http + rbac: + # When present, restricts secrets the server can read to a given list. + secretWhitelist: [] + serviceAccount: argo-server + # Whether to create the service account with the name specified in + # server.serviceAccount and bind it to the server role. + createServiceAccount: true + # Service account annotations + serviceAccountAnnotations: {} + # Annotations to be applied to the UI Service + serviceAnnotations: {} + # Optional labels to add to the UI Service + serviceLabels: {} + # Static IP address to assign to loadBalancer + # service type `LoadBalancer` + loadBalancerIP: "" + # Source ranges to allow access to service from. Only applies to + # service type `LoadBalancer` + loadBalancerSourceRanges: [] + resources: {} + replicas: 1 + pdb: + enabled: false + # minAvailable: 1 + # maxUnavailable: 1 + ## Node selectors and tolerations for server scheduling to nodes with taints + ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + ## + nodeSelector: + kubernetes.io/os: linux + tolerations: [] + affinity: {} + # Leverage a PriorityClass to ensure your pods survive resource shortages + # ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ + # PriorityClass: system-cluster-critical + priorityClassName: "" + + # Run the argo server in "secure" mode. Configure this value instead of + # "--secure" in extraArgs. See the following documentation for more details + # on secure mode: + # https://argoproj.github.io/argo/tls/#encrypted + secure: false + + # Extra arguments to provide to the Argo server binary. + extraArgs: [] + + ## Additional volumes to the server main container. + volumeMounts: [] + volumes: [] + + ## Ingress configuration. + ## ref: https://kubernetes.io/docs/user-guide/ingress/ + ## + ingress: + enabled: false + + ## Annotations to be added to the web ingress. + ## + # annotations: + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + + ## Hostnames. + ## Must be provided if Ingress is enabled. + ## + # hosts: + # - argo.domain.com + + ## Additional Paths for each host + # paths: + # - serviceName: "ssl-redirect" + # servicePort: "use-annotation" + + ## TLS configuration. + ## Secrets must be manually created in the namespace. + ## + # tls: + # - secretName: argo-ui-tls + # hosts: + # - argo.domain.com + clusterWorkflowTemplates: + # Give the server permissions to edit ClusterWorkflowTemplates. + enableEditing: true + sso: + ## SSO configuration when SSO is specified as a server auth mode. + ## All the values are requied. SSO is activated by adding --auth-mode=sso + ## to the server command line. + # + ## The root URL of the OIDC identity provider. + # issuer: https://accounts.google.com + ## Name of a secret and a key in it to retrieve the app OIDC client ID from. + # clientId: + # name: argo-server-sso + # key: client-id + ## Name of a secret and a key in it to retrieve the app OIDC client secret from. + # clientSecret: + # name: argo-server-sso + # key: client-secret + ## The OIDC redirect URL. Should be in the form /oauth2/callback. + # redirectUrl: https://argo/oauth2/callback + +# Influences the creation of the ConfigMap for the workflow-controller itself. +useDefaultArtifactRepo: false +useStaticCredentials: true +artifactRepository: + # archiveLogs will archive the main container logs as an artifact + archiveLogs: false + s3: + # Note the `key` attribute is not the actual secret, it's the PATH to + # the contents in the associated secret, as defined by the `name` attribute. + accessKeySecret: + # name: -minio (default) + key: accesskey + secretKeySecret: + # name: -minio + key: secretkey + insecure: true + # bucket: + # endpoint: + # region: + # roleARN: + # useSDKCreds: true + # gcs: + # bucket: -argo + # keyFormat: "{{workflow.namespace}}/{{workflow.name}}/" + # serviceAccountKeySecret is a secret selector. + # It references the k8s secret named 'my-gcs-credentials'. + # This secret is expected to have have the key 'serviceAccountKey', + # containing the base64 encoded credentials + # to the bucket. + # + # If it's running on GKE and Workload Identity is used, + # serviceAccountKeySecret is not needed. + # serviceAccountKeySecret: + # name: my-gcs-credentials + # key: serviceAccountKey + + +# NOTE: These are setting attributes for the `minio` optional dependency +minio: + # If set to true then chart installs minio and generate according artifactRepository section in workflow controller config map + install: false + defaultBucket: + enabled: true + name: argo-artifacts diff --git a/applications/argo/deploy/templates/argo-sa.yaml b/applications/argo/deploy/templates/argo-sa.yaml index 91bfe691..46416e05 100644 --- a/applications/argo/deploy/templates/argo-sa.yaml +++ b/applications/argo/deploy/templates/argo-sa.yaml @@ -7,7 +7,7 @@ metadata: apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: - name: {{ .Values.apps.argo.serviceaccount }}-access-1 + name: {{ .Release.Namespace }}-{{ .Values.apps.argo.serviceaccount }}-access-1 namespace: {{ .Release.Namespace }} roleRef: apiGroup: rbac.authorization.k8s.io @@ -18,36 +18,16 @@ subjects: name: {{ .Values.apps.argo.serviceaccount }} namespace: {{ .Release.Namespace }} --- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ .Values.apps.argo.serviceaccount }} - namespace: {{ .Values.apps.argo.workflows_namespace }} ---- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: - name: {{ .Values.apps.argo.serviceaccount }}-access-2 - namespace: {{ .Values.apps.argo.workflows_namespace }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -subjects: -- kind: ServiceAccount - name: {{ .Values.apps.argo.serviceaccount }} - namespace: {{ .Values.apps.argo.workflows_namespace }} ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: {{ .Values.apps.argo.serviceaccount }}-access-3 - namespace: {{ .Values.apps.argo.workflows_namespace }} + name: {{ .Release.Namespace }}-{{ .Values.apps.argo.serviceaccount }}-access-2 + namespace: {{ .Release.Namespace }} roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount - name: cloudharness - namespace: default \ No newline at end of file + name: default + namespace: {{ .Release.Namespace }} \ No newline at end of file diff --git a/applications/argo/deploy/values.yaml b/applications/argo/deploy/values.yaml index caea801f..cdc4b2a6 100644 --- a/applications/argo/deploy/values.yaml +++ b/applications/argo/deploy/values.yaml @@ -1,12 +1,10 @@ harness: subdomain: argo secured: true - name: argo-proxy1 + name: argo service: - port: 80 + port: 2746 auto: false - name: argo-ui + name: argo-server serviceaccount: argo-workflows -namespace: argo.svc.cluster.local -workflows_namespace: argo-workflows diff --git a/applications/common/api/openapi.yaml b/applications/common/api/openapi.yaml index 37e7e958..17d77534 100644 --- a/applications/common/api/openapi.yaml +++ b/applications/common/api/openapi.yaml @@ -33,3 +33,28 @@ paths: type: string summary: Gets the Sentry DSN for a given application x-openapi-router-controller: common.controllers.sentry_controller + /accounts/config: + get: + tags: + - Accounts + description: Gets the config for logging in into accounts + operationId: get_config + responses: + '200': + description: Config for accounts log in + content: + application/json: + schema: + type: object + properties: + url: + type: string + description: The auth URL. + realm: + type: string + description: The realm. + clientId: + type: string + description: The clientID. + summary: Gets the config for logging in into accounts + x-openapi-router-controller: common.controllers.accounts_controller diff --git a/applications/common/deploy/values.yaml b/applications/common/deploy/values.yaml index 6e68ff43..c40d5615 100644 --- a/applications/common/deploy/values.yaml +++ b/applications/common/deploy/values.yaml @@ -1,19 +1,21 @@ harness: - subdomain: common - secured: false - service: - auto: true - port: 8080 - name: common - deployment: - auto: true - name: common - port: 8080 - resources: - requests: - memory: 128Mi - cpu: 100m - limits: - memory: 256Mi - cpu: 200m - \ No newline at end of file + subdomain: common + secured: false + service: + auto: true + port: 8080 + name: common + deployment: + auto: true + name: common + port: 8080 + resources: + requests: + memory: 128Mi + cpu: 50m + limits: + memory: 256Mi + cpu: 200m + dependencies: + build: + - cloudharness-flask \ No newline at end of file diff --git a/applications/common/server/.dockerignore b/applications/common/server/.dockerignore index f9619601..a05d73b5 100644 --- a/applications/common/server/.dockerignore +++ b/applications/common/server/.dockerignore @@ -4,7 +4,6 @@ README.md tox.ini git_push.sh test-requirements.txt -setup.py # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/applications/common/server/Dockerfile b/applications/common/server/Dockerfile index de16ed1b..b22f3277 100644 --- a/applications/common/server/Dockerfile +++ b/applications/common/server/Dockerfile @@ -1,24 +1,23 @@ ARG REGISTRY ARG TAG=latest -FROM ${REGISTRY}cloudharness-base:${TAG} +ARG CLOUDHARNESS_FLASK=${REGISTRY}cloudharness-flask:${TAG} -RUN apk update && apk add postgresql-dev gcc python3-dev musl-dev -#RUN apk add psycopg2 libpq-dev python-dev +FROM $CLOUDHARNESS_FLASK -RUN mkdir -p /usr/src/app -WORKDIR /usr/src/app +ENV MODULE_NAME=common -COPY requirements.txt /usr/src/app/ +ENV WORKERS=2 +ENV PORT=8080 +RUN apk update +RUN apk add postgresql-dev + +COPY ./requirements.txt /usr/src/app/ RUN pip3 install --no-cache-dir -r requirements.txt COPY . /usr/src/app -EXPOSE 8080 - ENV FLASK_ENV=production ENV APP_SETTINGS=common.config.ProductionConfig - -ENTRYPOINT ["python3"] - -CMD ["-m", "common"] +RUN pip3 install -e /usr/src/app +ENTRYPOINT gunicorn --workers=$WORKERS --bind=0.0.0.0:$PORT $MODULE_NAME.__main__:app \ No newline at end of file diff --git a/applications/common/server/common/__main__.py b/applications/common/server/common/__main__.py index 9d811a33..1ef03e4b 100644 --- a/applications/common/server/common/__main__.py +++ b/applications/common/server/common/__main__.py @@ -1,23 +1,14 @@ -import os +#!/usr/bin/env python3 -from flask import Flask +from cloudharness.utils.server import init_flask, main from flask_cors import CORS +from common.repository.db import open_db -import connexion - -from common import encoder - -def main(): - app = connexion.App(__name__, specification_dir='./openapi/') - app.app.config.from_object(os.environ['APP_SETTINGS']) - app.app.json_encoder = encoder.JSONEncoder - app.add_api('openapi.yaml', - arguments={'title': 'CH service API'}, - pythonic_params=True) - from .repository.db import open_db +def init_fn(app): + cors = CORS(app, resources={r"/api/*": {"origins": "*"}}) open_db(app) - cors = CORS(app.app, resources={r"/api/*": {"origins": "*"}}) - app.run(port=8080) + +app = init_flask(init_app_fn=open_db) if __name__ == '__main__': main() diff --git a/applications/common/server/common/config.py b/applications/common/server/common/config.py index 28dde6b1..23d0636f 100644 --- a/applications/common/server/common/config.py +++ b/applications/common/server/common/config.py @@ -1,5 +1,5 @@ import os -import logging +from cloudharness import log from cloudharness.utils.config import CloudharnessConfig as conf @@ -19,7 +19,7 @@ class Config(object): SENTRY_APP = conf.get_application_by_filter(name='sentry')[0].name SQLALCHEMY_DATABASE_URI = f'postgresql+psycopg2://{SENTRY_POSTGRES_APP.user}:{SENTRY_POSTGRES_APP.password}@{SENTRY_POSTGRES_APP.name}:{SENTRY_POSTGRES_APP.port}/{SENTRY_POSTGRES_APP.initialdb}' except: - logging.error("Cannot configure SENTRY") + log.error("Cannot configure SENTRY") diff --git a/applications/common/server/common/controllers/accounts_controller.py b/applications/common/server/common/controllers/accounts_controller.py new file mode 100644 index 00000000..90202ef3 --- /dev/null +++ b/applications/common/server/common/controllers/accounts_controller.py @@ -0,0 +1,22 @@ +from urllib.parse import urljoin + +from cloudharness import applications +from cloudharness.utils.config import CloudharnessConfig + +def get_config(): # noqa: E501 + """ + Gets the config for logging in into accounts + + :rtype: json + { + 'url': '', + 'realm': '', + 'clientId': '' + } + """ + accounts_app = applications.get_configuration('accounts') + return { + 'url': urljoin(accounts_app.get_public_address(), 'auth'), + 'realm': CloudharnessConfig.get_namespace(), + 'clientId': accounts_app['webclient']['id'] + } diff --git a/applications/common/server/common/controllers/sentry_controller.py b/applications/common/server/common/controllers/sentry_controller.py index 8ffd6cdc..c2c12888 100644 --- a/applications/common/server/common/controllers/sentry_controller.py +++ b/applications/common/server/common/controllers/sentry_controller.py @@ -1,37 +1,42 @@ -import connexion -import six +import os import requests -import urllib -from common import util - -from common.repository.sentry import get_token, get_dsn, SentryProjectNotFound - -from cloudharness.utils.env import get_sentry_service_cluster_address from cloudharness import applications +from cloudharness.utils.env import get_sentry_service_cluster_address +from common.repository.sentry import get_token, get_dsn, SentryProjectNotFound +try: + global_dsn = os.environ.get("SENTRY_DSN","") + if len(global_dsn) < 1: + global_dsn = None +except: + global_dsn = None def getdsn(appname): # noqa: E501 """ - Gets the Sentry DSN for a given application - + Gets the Sentry DSN for a given application or returns the global dsn when set + global dsn can be set using the kubectl command + kubectl create secret generic -n mnp mnp-sentry --from-literal=dsn= :param appname: :type appname: str - :rtype: str """ ch_app = applications.get_configuration(appname) if ch_app.is_sentry_enabled(): - try: - dsn = get_dsn(appname) - except SentryProjectNotFound as e: - # if project not found, create one - sentry_api_token = get_token() - headers = {'Authorization': 'Bearer ' + sentry_api_token} - url = get_sentry_service_cluster_address() + f'/api/0/teams/sentry/sentry/projects/' - data = {'name' : appname} - response = requests.post(url, data, headers=headers, verify=False) - dsn = get_dsn(appname) + if global_dsn: + # if a global dsn env var is set and not empty then use this + dsn = global_dsn + else: + try: + dsn = get_dsn(appname) + except SentryProjectNotFound as e: + # if project not found, create one + sentry_api_token = get_token() + headers = {'Authorization': 'Bearer ' + sentry_api_token} + url = get_sentry_service_cluster_address() + f'/api/0/teams/sentry/sentry/projects/' + data = {'name' : appname} + response = requests.post(url, data, headers=headers, verify=False) + dsn = get_dsn(appname) else: dsn = '' return {'dsn': dsn} diff --git a/applications/common/server/common/encoder.py b/applications/common/server/common/encoder.py deleted file mode 100644 index a88fe1fc..00000000 --- a/applications/common/server/common/encoder.py +++ /dev/null @@ -1,20 +0,0 @@ -from connexion.apps.flask_app import FlaskJSONEncoder -import six - -from common.models.base_model_ import Model - - -class JSONEncoder(FlaskJSONEncoder): - include_nulls = False - - def default(self, o): - if isinstance(o, Model): - dikt = {} - for attr, _ in six.iteritems(o.openapi_types): - value = getattr(o, attr) - if value is None and not self.include_nulls: - continue - attr = o.attribute_map[attr] - dikt[attr] = value - return dikt - return FlaskJSONEncoder.default(self, o) diff --git a/applications/common/server/common/openapi/openapi.yaml b/applications/common/server/common/openapi/openapi.yaml index 992e266e..db8fef6a 100644 --- a/applications/common/server/common/openapi/openapi.yaml +++ b/applications/common/server/common/openapi/openapi.yaml @@ -13,27 +13,50 @@ tags: name: Sentry paths: /sentry/getdsn/{appname}: - get: - description: Gets the Sentry DSN for a given application - operationId: getdsn - parameters: - - explode: false - in: path + parameters: + - in: path name: appname - required: true schema: type: string - style: simple + required: true + get: + tags: + - Sentry + description: Gets the Sentry DSN for a given application + operationId: getdsn responses: - "200": + '200': + description: Sentry DSN for the given application content: application/json: schema: type: string - description: Sentry DSN for the given application summary: Gets the Sentry DSN for a given application - tags: - - Sentry x-openapi-router-controller: common.controllers.sentry_controller + /accounts/config: + get: + tags: + - Accounts + description: Gets the config for logging in into accounts + operationId: get_config + responses: + '200': + description: Config for accounts log in + content: + application/json: + schema: + type: object + properties: + url: + type: string + description: The auth URL. + realm: + type: string + description: The realm. + clientId: + type: string + description: The clientID. + summary: Gets the config for logging in into accounts + x-openapi-router-controller: common.controllers.accounts_controller components: schemas: {} diff --git a/applications/common/server/common/repository/db.py b/applications/common/server/common/repository/db.py index a76cb8bc..f0eba317 100644 --- a/applications/common/server/common/repository/db.py +++ b/applications/common/server/common/repository/db.py @@ -2,14 +2,16 @@ db = None + def get_db(): global db if not db: raise Exception('Database not open!') return db + def open_db(app): global db if not db: - db = SQLAlchemy(app.app) + db = SQLAlchemy(app) return db diff --git a/applications/common/server/requirements.txt b/applications/common/server/requirements.txt index af78e2e1..1ca458e3 100644 --- a/applications/common/server/requirements.txt +++ b/applications/common/server/requirements.txt @@ -9,7 +9,7 @@ swagger-ui-bundle >= 0.0.2 python_dateutil >= 2.6.0 setuptools >= 21.0.0 -psycopg2-binary==2.8.5 +psycopg2 Flask-SQLAlchemy==2.4.3 SQLAlchemy==1.3.17 requests==2.21.0 diff --git a/applications/common/server/setup.py b/applications/common/server/setup.py index 147f4f42..31e9ded2 100644 --- a/applications/common/server/setup.py +++ b/applications/common/server/setup.py @@ -16,7 +16,8 @@ REQUIRES = [ "connexion>=2.0.2", "swagger-ui-bundle>=0.0.2", - "python_dateutil>=2.6.0" + "python_dateutil>=2.6.0", + "psycopg2" ] setup( diff --git a/applications/events/Dockerfile b/applications/events/Dockerfile new file mode 100644 index 00000000..14d4e987 --- /dev/null +++ b/applications/events/Dockerfile @@ -0,0 +1 @@ +FROM solsson/kafka-manager diff --git a/applications/events/deploy/templates/deployments.yml b/applications/events/deploy/templates/deployments.yml index ab91e7b6..a39f0a02 100644 --- a/applications/events/deploy/templates/deployments.yml +++ b/applications/events/deploy/templates/deployments.yml @@ -54,13 +54,15 @@ spec: readinessProbe: tcpSocket: port: 9092 - timeoutSeconds: 1 + timeoutSeconds: 2 + initialDelaySeconds: 30 + periodSeconds: 30 resources: limits: cpu: 500m memory: 600Mi requests: - cpu: 100m + cpu: 50m memory: 100Mi volumeMounts: - mountPath: /etc/kafka @@ -166,9 +168,21 @@ spec: - /bin/sh - -c - '[ "imok" = "$(echo ruok | nc -w 1 -q 1 127.0.0.1 2181)" ]' + timeoutSeconds: 3 + initialDelaySeconds: 30 + periodSeconds: 30 + livenessProbe: + exec: + command: + - /bin/sh + - -c + - '[ "imok" = "$(echo ruok | nc -w 1 -q 1 127.0.0.1 2181)" ]' + timeoutSeconds: 3 + initialDelaySeconds: 12 + periodSeconds: 60 resources: limits: - memory: 120Mi + memory: 500Mi requests: cpu: 10m memory: 100Mi @@ -264,9 +278,21 @@ spec: - /bin/sh - -c - '[ "imok" = "$(echo ruok | nc -w 1 -q 1 127.0.0.1 2181)" ]' + timeoutSeconds: 3 + initialDelaySeconds: 30 + periodSeconds: 30 + livenessProbe: + exec: + command: + - /bin/sh + - -c + - '[ "imok" = "$(echo ruok | nc -w 1 -q 1 127.0.0.1 2181)" ]' + timeoutSeconds: 3 + initialDelaySeconds: 12 + periodSeconds: 60 resources: limits: - memory: 120Mi + memory: 500Mi requests: cpu: 10m memory: 100Mi @@ -314,29 +340,3 @@ spec: requests: storage: 1Gi storageClassName: standard ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ .Values.apps.events.name }} -spec: - replicas: 1 - selector: - matchLabels: - app: {{ .Values.apps.events.name }} - template: - metadata: - labels: - app: {{ .Values.apps.events.name }} - spec: - containers: - - name: kafka-manager - image: solsson/kafka-manager@sha256:9da595ecbb733074a1d3c6091a1e0c384da4f4e1f19f4e16276062278da8e592 - ports: - - containerPort: 80 - env: - - name: ZK_HOSTS - value: zookeeper.{{ .Values.namespace }}:2181 - command: - - ./bin/kafka-manager - - -Dhttp.port=80 \ No newline at end of file diff --git a/applications/events/deploy/templates/roles.yml b/applications/events/deploy/templates/roles.yml index 370d3143..3d19bdd0 100644 --- a/applications/events/deploy/templates/roles.yml +++ b/applications/events/deploy/templates/roles.yml @@ -22,10 +22,9 @@ rules: - patch --- apiVersion: rbac.authorization.k8s.io/v1 -kind: Role +kind: ClusterRole metadata: - name: node-reader - namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-node-reader labels: origin: github.com_Yolean_kubernetes-kafka rules: @@ -42,7 +41,6 @@ metadata: labels: origin: github.com_Yolean_kubernetes-kafka name: kafka-pod-labler - namespace: {{ .Release.Namespace }} roleRef: apiGroup: rbac.authorization.k8s.io kind: Role @@ -50,18 +48,19 @@ roleRef: subjects: - kind: ServiceAccount name: kafka + namespace: {{ .Release.Namespace }} --- apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding +kind: ClusterRoleBinding metadata: labels: origin: github.com_Yolean_kubernetes-kafka - name: kafka-node-reader - namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-kafka-node-reader roleRef: apiGroup: rbac.authorization.k8s.io - kind: Role - name: node-reader + kind: ClusterRole + name: {{ .Release.Name }}-node-reader subjects: - kind: ServiceAccount name: kafka + namespace: {{ .Release.Namespace }} \ No newline at end of file diff --git a/applications/events/deploy/values.yaml b/applications/events/deploy/values.yaml index 37f1683d..a9f3996a 100644 --- a/applications/events/deploy/values.yaml +++ b/applications/events/deploy/values.yaml @@ -2,8 +2,15 @@ harness: subdomain: events secured: true service: + auto: true port: 80 + deployment: auto: true + port: 9000 + name: events + env: + - name: ZK_HOSTS + value: zookeeper:2181 kafka: name: bootstrap port: 9092 \ No newline at end of file diff --git a/applications/jupyterhub/deploy/templates/hub/deployment.yaml b/applications/jupyterhub/deploy/templates/hub/deployment.yaml index d4bdaf3e..c98a09a8 100755 --- a/applications/jupyterhub/deploy/templates/hub/deployment.yaml +++ b/applications/jupyterhub/deploy/templates/hub/deployment.yaml @@ -72,7 +72,7 @@ spec: {{- .Values.apps.jupyterhub.hub.extraContainers | toYaml | trimSuffix "\n" | nindent 8 }} {{- end }} - name: hub - image: {{ .Values.apps.jupyterhub.image }} + image: {{ .Values.apps.jupyterhub.harness.deployment.image }} command: - jupyterhub - --config diff --git a/applications/jupyterhub/deploy/templates/scheduling/user-scheduler/rbac.yaml b/applications/jupyterhub/deploy/templates/scheduling/user-scheduler/rbac.yaml index 825d7c6e..c67c4b43 100755 --- a/applications/jupyterhub/deploy/templates/scheduling/user-scheduler/rbac.yaml +++ b/applications/jupyterhub/deploy/templates/scheduling/user-scheduler/rbac.yaml @@ -7,7 +7,7 @@ metadata: labels: {{- include "jupyterhub.labels" . | nindent 4 }} --- -kind: ClusterRoleBinding +kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: {{ .Release.Name }}-user-scheduler-base @@ -19,11 +19,11 @@ subjects: name: user-scheduler namespace: {{ .Release.Namespace }} roleRef: - kind: ClusterRole + kind: Role name: system:kube-scheduler apiGroup: rbac.authorization.k8s.io --- -kind: ClusterRole +kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: name: {{ .Release.Name }}-user-scheduler-complementary @@ -45,7 +45,7 @@ rules: resources: ["persistentvolume", "persistentvolumeclaims"] verbs: ["update"] --- -kind: ClusterRoleBinding +kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: {{ .Release.Name }}-user-scheduler-complementary @@ -57,7 +57,7 @@ subjects: name: user-scheduler namespace: {{ .Release.Namespace }} roleRef: - kind: ClusterRole + kind: Role name: {{ .Release.Name }}-user-scheduler-complementary apiGroup: rbac.authorization.k8s.io {{- end }} diff --git a/applications/jupyterhub/deploy/values.yaml b/applications/jupyterhub/deploy/values.yaml index 08ec0c64..f4244350 100755 --- a/applications/jupyterhub/deploy/values.yaml +++ b/applications/jupyterhub/deploy/values.yaml @@ -106,8 +106,8 @@ proxy: enabled: false resources: requests: - cpu: 200m - memory: 512Mi + cpu: 50m + memory: 128Mi nginx: image: name: quay.io/kubernetes-ingress-controller/nginx-ingress-controller @@ -215,11 +215,11 @@ singleuser: enabled: false startTimeout: 300 cpu: - limit: null - guarantee: null + limit: 400m + guarantee: 50m memory: - limit: null - guarantee: 0.5G + limit: 0.5G + guarantee: 0.1G extraResource: limits: {} guarantees: {} @@ -240,7 +240,7 @@ scheduling: resources: requests: cpu: 50m - memory: 256Mi + memory: 128Mi podPriority: enabled: false userPlaceholder: diff --git a/applications/samples/.dockerignore b/applications/samples/.dockerignore new file mode 100644 index 00000000..f06235c4 --- /dev/null +++ b/applications/samples/.dockerignore @@ -0,0 +1,2 @@ +node_modules +dist diff --git a/applications/samples/Dockerfile b/applications/samples/Dockerfile new file mode 100644 index 00000000..3c52c4d1 --- /dev/null +++ b/applications/samples/Dockerfile @@ -0,0 +1,33 @@ +ARG REGISTRY +ARG TAG=latest +ARG CLOUDHARNESS_FRONTEND_BUILD=${REGISTRY}cloudharness-frontend-build:${TAG} +ARG CLOUDHARNESS_FLASK=${REGISTRY}cloudharness-flask:${TAG} + +FROM $CLOUDHARNESS_FRONTEND_BUILD as frontend + +ENV APP_DIR=/app + +WORKDIR ${APP_DIR} +COPY frontend/package.json ${APP_DIR} +COPY frontend/package-lock.json ${APP_DIR} +RUN npm ci + +COPY frontend ${APP_DIR} +RUN npm run build + +##### +FROM $CLOUDHARNESS_FLASK +ENV MODULE_NAME=samples + +ENV WORKERS=2 +ENV PORT=8080 + +COPY backend/requirements.txt /usr/src/app/ + +RUN pip3 install --no-cache-dir -r requirements.txt + +COPY backend/ /usr/src/app + +COPY --from=frontend app/dist/ /usr/src/app/www + +RUN pip3 install -e . \ No newline at end of file diff --git a/applications/samples/README.md b/applications/samples/README.md index 399a8543..e69de29b 100644 --- a/applications/samples/README.md +++ b/applications/samples/README.md @@ -1,3 +0,0 @@ -Temporary: we are using it to test the token generation. - -TODO move into neuroimaging \ No newline at end of file diff --git a/applications/samples/api/config.json b/applications/samples/api/config.json index 0dd0c28f..09363dc2 100644 --- a/applications/samples/api/config.json +++ b/applications/samples/api/config.json @@ -1,3 +1 @@ -{ - "packageName": "api_samples" -} \ No newline at end of file +{"packageName": "cloudharness_cli.samples"} \ No newline at end of file diff --git a/applications/samples/api/samples.yaml b/applications/samples/api/samples.yaml index f957880f..e25f852f 100644 --- a/applications/samples/api/samples.yaml +++ b/applications/samples/api/samples.yaml @@ -40,7 +40,7 @@ paths: summary: test sentry is working operationId: error tags: - - workflows + - test responses: "500": description: Sentry entry should come! @@ -50,7 +50,21 @@ paths: application/json: schema: type: string - + /ping: + get: + summary: test the application is up + operationId: ping + tags: + - test + responses: + "500": + description: This shouldn't happen + "200": + description: What we want + content: + application/json: + schema: + type: string /operation_sync: get: @@ -117,7 +131,7 @@ paths: type: string example: my-op servers: - - url: https://samples.cloudharness.metacell.us/api + - url: /api components: securitySchemes: bearerAuth: diff --git a/applications/samples/server/.dockerignore b/applications/samples/backend/.dockerignore similarity index 100% rename from applications/samples/server/.dockerignore rename to applications/samples/backend/.dockerignore diff --git a/applications/samples/server/.gitignore b/applications/samples/backend/.gitignore similarity index 99% rename from applications/samples/server/.gitignore rename to applications/samples/backend/.gitignore index 43995bd4..74b5ddfb 100644 --- a/applications/samples/server/.gitignore +++ b/applications/samples/backend/.gitignore @@ -64,3 +64,5 @@ target/ #Ipython Notebook .ipynb_checkpoints + +www diff --git a/applications/samples/server/.openapi-generator-ignore b/applications/samples/backend/.openapi-generator-ignore similarity index 97% rename from applications/samples/server/.openapi-generator-ignore rename to applications/samples/backend/.openapi-generator-ignore index 5cc13cc6..54faff66 100644 --- a/applications/samples/server/.openapi-generator-ignore +++ b/applications/samples/backend/.openapi-generator-ignore @@ -23,5 +23,5 @@ #!docs/README.md setup.py */controllers/* -*/models/* -Dockerfile \ No newline at end of file +Dockerfile +src/__main__.py \ No newline at end of file diff --git a/applications/samples/server/.travis.yml b/applications/samples/backend/.travis.yml similarity index 100% rename from applications/samples/server/.travis.yml rename to applications/samples/backend/.travis.yml diff --git a/applications/samples/server/README.md b/applications/samples/backend/README.md similarity index 88% rename from applications/samples/server/README.md rename to applications/samples/backend/README.md index b1e6a1f9..d4e04c30 100644 --- a/applications/samples/server/README.md +++ b/applications/samples/backend/README.md @@ -15,7 +15,7 @@ To run the server, please execute the following from the root directory: ``` pip3 install -r requirements.txt -python3 -m api_samples +python3 -m cloudharness_cli.samples ``` and open your browser to here: @@ -42,8 +42,8 @@ To run the server on a Docker container, please execute the following from the r ```bash # building the image -docker build -t api_samples . +docker build -t cloudharness_cli.samples . # starting up a container -docker run -p 8080:8080 api_samples +docker run -p 8080:8080 cloudharness_cli.samples ``` \ No newline at end of file diff --git a/applications/samples/server/git_push.sh b/applications/samples/backend/git_push.sh similarity index 100% rename from applications/samples/server/git_push.sh rename to applications/samples/backend/git_push.sh diff --git a/applications/samples/backend/requirements.txt b/applications/samples/backend/requirements.txt new file mode 100644 index 00000000..72ed547c --- /dev/null +++ b/applications/samples/backend/requirements.txt @@ -0,0 +1,10 @@ +connexion[swagger-ui] >= 2.6.0; python_version>="3.6" +# 2.3 is the last version that supports python 3.4-3.5 +connexion[swagger-ui] <= 2.3.0; python_version=="3.5" or python_version=="3.4" +# connexion requires werkzeug but connexion < 2.4.0 does not install werkzeug +# we must peg werkzeug versions below to fix connexion +# https://github.com/zalando/connexion/pull/1044 +werkzeug == 0.16.1; python_version=="3.5" or python_version=="3.4" +swagger-ui-bundle >= 0.0.2 +python_dateutil >= 2.6.0 +setuptools >= 21.0.0 diff --git a/applications/samples/backend/samples/__init__.py b/applications/samples/backend/samples/__init__.py new file mode 100644 index 00000000..2b355798 --- /dev/null +++ b/applications/samples/backend/samples/__init__.py @@ -0,0 +1,5 @@ +import inspect +import os + + + diff --git a/applications/samples/backend/samples/__main__.py b/applications/samples/backend/samples/__main__.py new file mode 100644 index 00000000..3118318a --- /dev/null +++ b/applications/samples/backend/samples/__main__.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python3 + +from cloudharness.utils.server import init_flask, main + + +app = init_flask(title="Cloudharness sample application", webapp=True) + +if __name__ == '__main__': + main() diff --git a/applications/samples/server/api_samples/__init__.py b/applications/samples/backend/samples/controllers/__init__.py similarity index 100% rename from applications/samples/server/api_samples/__init__.py rename to applications/samples/backend/samples/controllers/__init__.py diff --git a/applications/samples/server/api_samples/controllers/auth_controller.py b/applications/samples/backend/samples/controllers/auth_controller.py similarity index 73% rename from applications/samples/server/api_samples/controllers/auth_controller.py rename to applications/samples/backend/samples/controllers/auth_controller.py index 6561b554..86992c01 100644 --- a/applications/samples/server/api_samples/controllers/auth_controller.py +++ b/applications/samples/backend/samples/controllers/auth_controller.py @@ -1,8 +1,8 @@ import connexion import six -from api_samples.models.valid import Valid # noqa: E501 -from api_samples import util +from samples.models.valid import Valid # noqa: E501 +from samples import util def valid_token(): # noqa: E501 diff --git a/applications/samples/backend/samples/controllers/security_controller_.py b/applications/samples/backend/samples/controllers/security_controller_.py new file mode 100644 index 00000000..8dd254a2 --- /dev/null +++ b/applications/samples/backend/samples/controllers/security_controller_.py @@ -0,0 +1,17 @@ +from typing import List + + +def info_from_bearerAuth(token): + """ + Check and retrieve authentication information from custom bearer token. + Returned value will be passed in 'token_info' parameter of your operation function, if there is one. + 'sub' or 'uid' will be set in 'user' parameter of your operation function, if there is one. + + :param token Token provided by Authorization header + :type token: str + :return: Decoded token information or None if token is invalid + :rtype: dict | None + """ + return {'uid': 'user_id'} + + diff --git a/applications/samples/backend/samples/controllers/test_controller.py b/applications/samples/backend/samples/controllers/test_controller.py new file mode 100644 index 00000000..1234ce1b --- /dev/null +++ b/applications/samples/backend/samples/controllers/test_controller.py @@ -0,0 +1,27 @@ +import connexion +import six + +from samples import util + + +def error(): # noqa: E501 + """test sentry is working + + # noqa: E501 + + + :rtype: str + """ + raise Exception("The error we supposed to find here") + + +def ping(): # noqa: E501 + """test the application is up + + # noqa: E501 + + + :rtype: str + """ + import time + return time.time() diff --git a/applications/samples/backend/samples/controllers/workflows_controller.py b/applications/samples/backend/samples/controllers/workflows_controller.py new file mode 100644 index 00000000..84d5e6d9 --- /dev/null +++ b/applications/samples/backend/samples/controllers/workflows_controller.py @@ -0,0 +1,80 @@ +import connexion +import six + +from samples.models.inline_response202 import InlineResponse202 # noqa: E501 +from samples import util +from samples.models import InlineResponse202 +from samples.models.inline_response202_task import InlineResponse202Task +from flask.json import jsonify + +from cloudharness import log + +try: + from cloudharness.workflows import operations, tasks +except Exception as e: + log.error("Cannot start workflows module. Probably this is related some problem with the kubectl configuration", exc_info=True) + + +def submit_async(): # noqa: E501 + """Send an asyncronous operation + + # noqa: E501 + + + :rtype: InlineResponse202 + """ + shared_directory = '/mnt/shared' + task_write = tasks.CustomTask('download-file', 'workflows-extract-download', + url='https://github.com/MetaCell/cloud-harness/blob/master/README.md') + task_print = tasks.CustomTask( + 'print-file', 'workflows-print-file', file_path=shared_directory + '/README.md') + op = operations.PipelineOperation( + 'test-custom-connected-op-', (task_write, task_print), shared_directory=shared_directory) + + submitted = op.execute() + if not op.is_error(): + return InlineResponse202(task=InlineResponse202Task(href=op.get_operation_update_url(), name=submitted.name)), 202 + else: + return 'Error submitting operation', 500 + + +def submit_sync(): # noqa: E501 + """Send a syncronous operation + + # noqa: E501 + + + :rtype: str + """ + task = tasks.CustomTask( + 'download-file', 'workflows-extract-download', url='https://github.com/MetaCell/cloud-harness/blob/master/README.md') + + op = operations.DistributedSyncOperation('test-sync-op-', task) + try: + workflow = op.execute() + return workflow.raw.to_dict() + except Exception as e: + log.error('Error submitting sync operation', exc_info=True) + return 'Error submitting operation: %s' % e, 500 + + +def submit_sync_with_results(a=1, b=2): # noqa: E501 + """Send a synchronous operation and get results using the event queue. Just a sum, but in the cloud + + # noqa: E501 + + :param a: first number to sum + :type a: float + :param b: second number to sum + :type b: float + + :rtype: str + """ + task = tasks.CustomTask('test-sum', 'samples-sum', a=a, b=b) + try: + op = operations.DistributedSyncOperationWithResults( + 'test-sync-op-results-', task) + result = op.execute() + return result + except Exception as e: + return jsonify(str(e)), 200 diff --git a/applications/samples/backend/samples/models/__init__.py b/applications/samples/backend/samples/models/__init__.py new file mode 100644 index 00000000..f6868bc5 --- /dev/null +++ b/applications/samples/backend/samples/models/__init__.py @@ -0,0 +1,8 @@ +# coding: utf-8 + +# flake8: noqa +from __future__ import absolute_import +# import models into model package +from samples.models.inline_response202 import InlineResponse202 +from samples.models.inline_response202_task import InlineResponse202Task +from samples.models.valid import Valid diff --git a/applications/samples/server/api_samples/models/base_model_.py b/applications/samples/backend/samples/models/base_model_.py similarity index 98% rename from applications/samples/server/api_samples/models/base_model_.py rename to applications/samples/backend/samples/models/base_model_.py index 3ace029a..43064a03 100644 --- a/applications/samples/server/api_samples/models/base_model_.py +++ b/applications/samples/backend/samples/models/base_model_.py @@ -3,7 +3,7 @@ import six import typing -from api_samples import util +from samples import util T = typing.TypeVar('T') diff --git a/applications/samples/server/api_samples/models/inline_response202.py b/applications/samples/backend/samples/models/inline_response202.py similarity index 86% rename from applications/samples/server/api_samples/models/inline_response202.py rename to applications/samples/backend/samples/models/inline_response202.py index 9d389979..b6d2a3ca 100644 --- a/applications/samples/server/api_samples/models/inline_response202.py +++ b/applications/samples/backend/samples/models/inline_response202.py @@ -5,11 +5,11 @@ from typing import List, Dict # noqa: F401 -from api_samples.models.base_model_ import Model -from api_samples.models.inline_response202_task import InlineResponse202Task -from api_samples import util - +from samples.models.base_model_ import Model +from samples.models.inline_response202_task import InlineResponse202Task +from samples import util +from samples.models.inline_response202_task import InlineResponse202Task # noqa: E501 class InlineResponse202(Model): """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/applications/samples/server/api_samples/models/inline_response202_task.py b/applications/samples/backend/samples/models/inline_response202_task.py similarity index 96% rename from applications/samples/server/api_samples/models/inline_response202_task.py rename to applications/samples/backend/samples/models/inline_response202_task.py index 465a8824..e9a53b7f 100644 --- a/applications/samples/server/api_samples/models/inline_response202_task.py +++ b/applications/samples/backend/samples/models/inline_response202_task.py @@ -5,8 +5,8 @@ from typing import List, Dict # noqa: F401 -from api_samples.models.base_model_ import Model -from api_samples import util +from samples.models.base_model_ import Model +from samples import util class InlineResponse202Task(Model): diff --git a/applications/samples/server/api_samples/models/valid.py b/applications/samples/backend/samples/models/valid.py similarity index 94% rename from applications/samples/server/api_samples/models/valid.py rename to applications/samples/backend/samples/models/valid.py index eae6c5f4..769834e8 100644 --- a/applications/samples/server/api_samples/models/valid.py +++ b/applications/samples/backend/samples/models/valid.py @@ -5,8 +5,8 @@ from typing import List, Dict # noqa: F401 -from api_samples.models.base_model_ import Model -from api_samples import util +from samples.models.base_model_ import Model +from samples import util class Valid(Model): diff --git a/applications/samples/server/api_samples/openapi/openapi.yaml b/applications/samples/backend/samples/openapi/openapi.yaml similarity index 82% rename from applications/samples/server/api_samples/openapi/openapi.yaml rename to applications/samples/backend/samples/openapi/openapi.yaml index 9f8d242d..34af58d0 100644 --- a/applications/samples/server/api_samples/openapi/openapi.yaml +++ b/applications/samples/backend/samples/openapi/openapi.yaml @@ -27,8 +27,8 @@ paths: description: This won't happen summary: test sentry is working tags: - - workflows - x-openapi-router-controller: api_samples.controllers.workflows_controller + - test + x-openapi-router-controller: samples.controllers.test_controller /operation_async: get: operationId: submit_async @@ -42,7 +42,7 @@ paths: summary: Send an asynchronous operation tags: - workflows - x-openapi-router-controller: api_samples.controllers.workflows_controller + x-openapi-router-controller: samples.controllers.workflows_controller /operation_sync: get: operationId: submit_sync @@ -56,7 +56,7 @@ paths: summary: Send a synchronous operation tags: - workflows - x-openapi-router-controller: api_samples.controllers.workflows_controller + x-openapi-router-controller: samples.controllers.workflows_controller /operation_sync_results: get: operationId: submit_sync_with_results @@ -90,7 +90,23 @@ paths: Just a sum, but in the cloud tags: - workflows - x-openapi-router-controller: api_samples.controllers.workflows_controller + x-openapi-router-controller: samples.controllers.workflows_controller + /ping: + get: + operationId: ping + responses: + "500": + description: This shouldn't happen + "200": + content: + application/json: + schema: + type: string + description: What we want + summary: test the application is up + tags: + - test + x-openapi-router-controller: samples.controllers.test_controller /valid: get: description: | @@ -112,7 +128,7 @@ paths: summary: Check if the token is valid. Get a token by logging into the base url tags: - auth - x-openapi-router-controller: api_samples.controllers.auth_controller + x-openapi-router-controller: samples.controllers.auth_controller components: schemas: Valid: diff --git a/applications/samples/server/api_samples/controllers/__init__.py b/applications/samples/backend/samples/service/__init__.py similarity index 100% rename from applications/samples/server/api_samples/controllers/__init__.py rename to applications/samples/backend/samples/service/__init__.py diff --git a/applications/samples/server/api_samples/service/security_service.py b/applications/samples/backend/samples/service/security_service.py similarity index 100% rename from applications/samples/server/api_samples/service/security_service.py rename to applications/samples/backend/samples/service/security_service.py diff --git a/applications/samples/server/api_samples/test/__init__.py b/applications/samples/backend/samples/test/__init__.py similarity index 89% rename from applications/samples/server/api_samples/test/__init__.py rename to applications/samples/backend/samples/test/__init__.py index a2dbaf9d..156f6435 100644 --- a/applications/samples/server/api_samples/test/__init__.py +++ b/applications/samples/backend/samples/test/__init__.py @@ -3,7 +3,7 @@ import connexion from flask_testing import TestCase -from api_samples.encoder import JSONEncoder +from samples.encoder import JSONEncoder class BaseTestCase(TestCase): diff --git a/applications/samples/server/api_samples/test/test_auth_controller.py b/applications/samples/backend/samples/test/test_auth_controller.py similarity index 54% rename from applications/samples/server/api_samples/test/test_auth_controller.py rename to applications/samples/backend/samples/test/test_auth_controller.py index d68f15c1..eae38d06 100644 --- a/applications/samples/server/api_samples/test/test_auth_controller.py +++ b/applications/samples/backend/samples/test/test_auth_controller.py @@ -1,12 +1,13 @@ # coding: utf-8 from __future__ import absolute_import +import unittest from flask import json from six import BytesIO -from api_samples.models.valid import Valid # noqa: E501 -from api_samples.test import BaseTestCase +from samples.models.valid import Valid # noqa: E501 +from samples.test import BaseTestCase class TestAuthController(BaseTestCase): @@ -15,15 +16,19 @@ class TestAuthController(BaseTestCase): def test_valid_token(self): """Test case for valid_token - Check if the token is valid + Check if the token is valid. Get a token by logging into the base url """ + headers = { + 'Accept': 'application/json', + 'Authorization': 'Bearer special-key', + } response = self.client.open( - '/0.1.0/valid', - method='GET') + '/api/valid', + method='GET', + headers=headers) self.assert200(response, 'Response body is : ' + response.data.decode('utf-8')) if __name__ == '__main__': - import unittest unittest.main() diff --git a/applications/samples/backend/samples/test/test_test_controller.py b/applications/samples/backend/samples/test/test_test_controller.py new file mode 100644 index 00000000..cb399241 --- /dev/null +++ b/applications/samples/backend/samples/test/test_test_controller.py @@ -0,0 +1,47 @@ +# coding: utf-8 + +from __future__ import absolute_import +import unittest + +from flask import json +from six import BytesIO + +from samples.test import BaseTestCase + + +class TestTestController(BaseTestCase): + """TestController integration test stubs""" + + def test_error(self): + """Test case for error + + test sentry is working + """ + headers = { + 'Accept': 'application/json', + } + response = self.client.open( + '/api/error', + method='GET', + headers=headers) + self.assert200(response, + 'Response body is : ' + response.data.decode('utf-8')) + + def test_ping(self): + """Test case for ping + + test the application is up + """ + headers = { + 'Accept': 'application/json', + } + response = self.client.open( + '/api/ping', + method='GET', + headers=headers) + self.assert200(response, + 'Response body is : ' + response.data.decode('utf-8')) + + +if __name__ == '__main__': + unittest.main() diff --git a/applications/samples/backend/samples/test/test_workflows_controller.py b/applications/samples/backend/samples/test/test_workflows_controller.py new file mode 100644 index 00000000..95f313e0 --- /dev/null +++ b/applications/samples/backend/samples/test/test_workflows_controller.py @@ -0,0 +1,66 @@ +# coding: utf-8 + +from __future__ import absolute_import +import unittest + +from flask import json +from six import BytesIO + +from samples.models.inline_response202 import InlineResponse202 # noqa: E501 +from samples.test import BaseTestCase + + +class TestWorkflowsController(BaseTestCase): + """WorkflowsController integration test stubs""" + + def test_submit_async(self): + """Test case for submit_async + + Send an asynchronous operation + """ + headers = { + 'Accept': 'application/json', + } + response = self.client.open( + '/api/operation_async', + method='GET', + headers=headers) + self.assert200(response, + 'Response body is : ' + response.data.decode('utf-8')) + + def test_submit_sync(self): + """Test case for submit_sync + + Send a synchronous operation + """ + headers = { + 'Accept': 'application/json', + } + response = self.client.open( + '/api/operation_sync', + method='GET', + headers=headers) + self.assert200(response, + 'Response body is : ' + response.data.decode('utf-8')) + + def test_submit_sync_with_results(self): + """Test case for submit_sync_with_results + + Send a synchronous operation and get results using the event queue. Just a sum, but in the cloud + """ + query_string = [('a', 10), + ('b', 10)] + headers = { + 'Accept': 'application/json', + } + response = self.client.open( + '/api/operation_sync_results', + method='GET', + headers=headers, + query_string=query_string) + self.assert200(response, + 'Response body is : ' + response.data.decode('utf-8')) + + +if __name__ == '__main__': + unittest.main() diff --git a/applications/samples/server/api_samples/typing_utils.py b/applications/samples/backend/samples/typing_utils.py similarity index 100% rename from applications/samples/server/api_samples/typing_utils.py rename to applications/samples/backend/samples/typing_utils.py diff --git a/applications/samples/server/api_samples/util.py b/applications/samples/backend/samples/util.py similarity index 98% rename from applications/samples/server/api_samples/util.py rename to applications/samples/backend/samples/util.py index 6e8baa5f..96dd696b 100644 --- a/applications/samples/server/api_samples/util.py +++ b/applications/samples/backend/samples/util.py @@ -2,7 +2,7 @@ import six import typing -from api_samples import typing_utils +from samples import typing_utils def _deserialize(data, klass): diff --git a/applications/samples/server/setup.py b/applications/samples/backend/setup.py similarity index 89% rename from applications/samples/server/setup.py rename to applications/samples/backend/setup.py index 3e72420c..728e2e2e 100644 --- a/applications/samples/server/setup.py +++ b/applications/samples/backend/setup.py @@ -3,7 +3,7 @@ import sys from setuptools import setup, find_packages -NAME = "api_samples" +NAME = "samples" VERSION = "1.0.0" # To install the library, run the following @@ -33,7 +33,7 @@ package_data={'': ['openapi/openapi.yaml']}, include_package_data=True, entry_points={ - 'console_scripts': ['api_samples=api_samples.__main__:main']}, + 'console_scripts': ['samples=samples.__main__:main']}, long_description="""\ CloudHarness Sample api """ diff --git a/applications/samples/server/test-requirements.txt b/applications/samples/backend/test-requirements.txt similarity index 84% rename from applications/samples/server/test-requirements.txt rename to applications/samples/backend/test-requirements.txt index a2626d87..0970f28c 100644 --- a/applications/samples/server/test-requirements.txt +++ b/applications/samples/backend/test-requirements.txt @@ -1,4 +1,4 @@ pytest~=4.6.7 # needed for python 2.7+3.4 pytest-cov>=2.8.1 pytest-randomly==1.2.3 # needed for python 2.7+3.4 -flask_testing==0.6.1 \ No newline at end of file +Flask-Testing==0.8.0 diff --git a/applications/samples/server/tox.ini b/applications/samples/backend/tox.ini similarity index 62% rename from applications/samples/server/tox.ini rename to applications/samples/backend/tox.ini index 8f380ee0..4134fd4f 100644 --- a/applications/samples/server/tox.ini +++ b/applications/samples/backend/tox.ini @@ -1,9 +1,11 @@ [tox] envlist = py3 +skipsdist=True [testenv] deps=-r{toxinidir}/requirements.txt -r{toxinidir}/test-requirements.txt + {toxinidir} commands= - pytest --cov=api_samples \ No newline at end of file + pytest --cov=cloudharness_cli.samples diff --git a/applications/samples/deploy/resources/example.yaml b/applications/samples/deploy/resources/example.yaml new file mode 100644 index 00000000..fb587c6d --- /dev/null +++ b/applications/samples/deploy/resources/example.yaml @@ -0,0 +1,3 @@ +hey: "this" +is: "a" +yaml: "file" \ No newline at end of file diff --git a/applications/samples/deploy/resources/myConfig.json b/applications/samples/deploy/resources/myConfig.json new file mode 100644 index 00000000..84b7fe06 --- /dev/null +++ b/applications/samples/deploy/resources/myConfig.json @@ -0,0 +1,3 @@ +{ + "name": "hello" +} \ No newline at end of file diff --git a/applications/samples/deploy/values-prod.yaml b/applications/samples/deploy/values-prod.yaml new file mode 100644 index 00000000..6a705ff5 --- /dev/null +++ b/applications/samples/deploy/values-prod.yaml @@ -0,0 +1,5 @@ +harness: + deployment: + resources: + requests: + memory: "33Mi" \ No newline at end of file diff --git a/applications/samples/deploy/values.yaml b/applications/samples/deploy/values.yaml index ecff24d9..0fc5df32 100644 --- a/applications/samples/deploy/values.yaml +++ b/applications/samples/deploy/values.yaml @@ -9,3 +9,22 @@ harness: deployment: auto: true port: 8080 + env: + - name: WORKERS + value: "3" + dependencies: + soft: + - workflows + - events + - accounts + build: + - cloudharness-flask + - cloudharness-frontend-build + resources: + - name: my-config + src: "myConfig.json" + dst: "/tmp/resources/myConfig.json" + - name: example + src: "example.yaml" + dst: "/usr/src/app/important_config.yaml" + diff --git a/applications/samples/frontend/.babelrc b/applications/samples/frontend/.babelrc new file mode 100644 index 00000000..2b53150f --- /dev/null +++ b/applications/samples/frontend/.babelrc @@ -0,0 +1,20 @@ +{ + "presets": [ + "@babel/preset-env", + "@babel/preset-react" + ], + "env": { + "production":{ + "presets": ["minify"] + } + }, + "plugins": [ + "@babel/transform-regenerator", + "@babel/plugin-proposal-class-properties", + [ + "module-resolver", { + "root": ["./src"] + } + ] + ] +} \ No newline at end of file diff --git a/applications/samples/frontend/.dockerignore b/applications/samples/frontend/.dockerignore new file mode 100644 index 00000000..cf709889 --- /dev/null +++ b/applications/samples/frontend/.dockerignore @@ -0,0 +1 @@ +**/node_modules diff --git a/applications/samples/frontend/.eslintignore b/applications/samples/frontend/.eslintignore new file mode 100644 index 00000000..77738287 --- /dev/null +++ b/applications/samples/frontend/.eslintignore @@ -0,0 +1 @@ +dist/ \ No newline at end of file diff --git a/applications/samples/frontend/.eslintrc.yml b/applications/samples/frontend/.eslintrc.yml new file mode 100644 index 00000000..68fb53e5 --- /dev/null +++ b/applications/samples/frontend/.eslintrc.yml @@ -0,0 +1,49 @@ +--- +root: true +extends: + - eslint:recommended + - plugin:react/recommended +parser: 'babel-eslint' +parserOptions: + ecmaFeatures: + jsx: true +plugins: + - jest + - react + - react-hooks +settings: + react: + version: detect +env: + jest/globals: true + browser: true + es6: true +rules: + no-console: 0 + func-style: 2 + consistent-return: 2 + prefer-arrow-callback: + - 2 + - allowNamedFunctions: false + allowUnboundThis: false + jest/no-disabled-tests: 2 + jest/no-focused-tests: 2 + react/prop-types: 0 + react/forbid-prop-types: 0 + react/no-unused-prop-types: 0 + react-hooks/rules-of-hooks: 2 + react-hooks/exhaustive-deps: 1 + curly: 2 + no-tabs: 2 + arrow-spacing: 2 + no-unneeded-ternary: 2 + object-curly-spacing: + - 2 + - always + indent: + - 2 + - 2 + - SwitchCase: 1 +globals: + __dirname: writable + module: writable \ No newline at end of file diff --git a/applications/samples/frontend/.gitignore b/applications/samples/frontend/.gitignore new file mode 100644 index 00000000..149b5765 --- /dev/null +++ b/applications/samples/frontend/.gitignore @@ -0,0 +1,4 @@ +wwwroot/*.js +node_modules +typings +dist diff --git a/applications/samples/frontend/README.md b/applications/samples/frontend/README.md new file mode 100644 index 00000000..7de3e72e --- /dev/null +++ b/applications/samples/frontend/README.md @@ -0,0 +1 @@ +# samples diff --git a/applications/samples/frontend/build.yaml b/applications/samples/frontend/build.yaml new file mode 100644 index 00000000..cbed1458 --- /dev/null +++ b/applications/samples/frontend/build.yaml @@ -0,0 +1,2 @@ +build_arguments: + - MY_ARG=${{MY_ARG}} \ No newline at end of file diff --git a/applications/samples/frontend/package-lock.json b/applications/samples/frontend/package-lock.json new file mode 100644 index 00000000..9f88d053 --- /dev/null +++ b/applications/samples/frontend/package-lock.json @@ -0,0 +1,8800 @@ +{ + "name": "samples", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/compat-data": { + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.12.7.tgz", + "integrity": "sha512-YaxPMGs/XIWtYqrdEOZOCPsVWfEoriXopnsz3/i7apYPXQ3698UFhS6dVT1KN5qOsWmVgw/FOrmQgpRaZayGsw==", + "dev": true + }, + "@babel/core": { + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.10.tgz", + "integrity": "sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.12.10", + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helpers": "^7.12.5", + "@babel/parser": "^7.12.10", + "@babel/template": "^7.12.7", + "@babel/traverse": "^7.12.10", + "@babel/types": "^7.12.10", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "semver": "^5.4.1", + "source-map": "^0.5.0" + } + }, + "@babel/generator": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.11.tgz", + "integrity": "sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA==", + "dev": true, + "requires": { + "@babel/types": "^7.12.11", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.10.tgz", + "integrity": "sha512-XplmVbC1n+KY6jL8/fgLVXXUauDIB+lD5+GsQEh6F6GBF1dq1qy4DP4yXWzDKcoqXB3X58t61e85Fitoww4JVQ==", + "dev": true, + "requires": { + "@babel/types": "^7.12.10" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz", + "integrity": "sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg==", + "dev": true, + "requires": { + "@babel/helper-explode-assignable-expression": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.5.tgz", + "integrity": "sha512-+qH6NrscMolUlzOYngSBMIOQpKUGPPsc61Bu5W10mg84LxZ7cmvnBHzARKbDoFxVvqqAbj6Tg6N7bSrWSPXMyw==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.12.5", + "@babel/helper-validator-option": "^7.12.1", + "browserslist": "^4.14.5", + "semver": "^5.5.0" + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.1.tgz", + "integrity": "sha512-hkL++rWeta/OVOBTRJc9a5Azh5mt5WgZUGAKMD8JM141YsE08K//bp1unBBieO6rUKkIPyUE0USQ30jAy3Sk1w==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-member-expression-to-functions": "^7.12.1", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/helper-replace-supers": "^7.12.1", + "@babel/helper-split-export-declaration": "^7.10.4" + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.7.tgz", + "integrity": "sha512-idnutvQPdpbduutvi3JVfEgcVIHooQnhvhx0Nk9isOINOIGYkZea1Pk2JlJRiUnMefrlvr0vkByATBY/mB4vjQ==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "regexpu-core": "^4.7.1" + } + }, + "@babel/helper-define-map": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz", + "integrity": "sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/types": "^7.10.5", + "lodash": "^4.17.19" + } + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.12.1.tgz", + "integrity": "sha512-dmUwH8XmlrUpVqgtZ737tK88v07l840z9j3OEhCLwKTkjlvKpfqXVIZ0wpK3aeOxspwGrf/5AP5qLx4rO3w5rA==", + "dev": true, + "requires": { + "@babel/types": "^7.12.1" + } + }, + "@babel/helper-function-name": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz", + "integrity": "sha512-AtQKjtYNolKNi6nNNVLQ27CP6D9oFR6bq/HPYSizlzbp7uC1M59XJe8L+0uXjbIaZaUJF99ruHqVGiKXU/7ybA==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.12.10", + "@babel/template": "^7.12.7", + "@babel/types": "^7.12.11" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz", + "integrity": "sha512-mm0n5BPjR06wh9mPQaDdXWDoll/j5UpCAPl1x8fS71GHm7HA6Ua2V4ylG1Ju8lvcTOietbPNNPaSilKj+pj+Ag==", + "dev": true, + "requires": { + "@babel/types": "^7.12.10" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz", + "integrity": "sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.7.tgz", + "integrity": "sha512-DCsuPyeWxeHgh1Dus7APn7iza42i/qXqiFPWyBDdOFtvS581JQePsc1F/nD+fHrcswhLlRc2UpYS1NwERxZhHw==", + "dev": true, + "requires": { + "@babel/types": "^7.12.7" + } + }, + "@babel/helper-module-imports": { + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz", + "integrity": "sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA==", + "dev": true, + "requires": { + "@babel/types": "^7.12.5" + } + }, + "@babel/helper-module-transforms": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz", + "integrity": "sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.12.1", + "@babel/helper-replace-supers": "^7.12.1", + "@babel/helper-simple-access": "^7.12.1", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/helper-validator-identifier": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.12.1", + "@babel/types": "^7.12.1", + "lodash": "^4.17.19" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.10.tgz", + "integrity": "sha512-4tpbU0SrSTjjt65UMWSrUOPZTsgvPgGG4S8QSTNHacKzpS51IVWGDj0yCwyeZND/i+LSN2g/O63jEXEWm49sYQ==", + "dev": true, + "requires": { + "@babel/types": "^7.12.10" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", + "dev": true + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.12.1.tgz", + "integrity": "sha512-9d0KQCRM8clMPcDwo8SevNs+/9a8yWVVmaE80FGJcEP8N1qToREmWEGnBn8BUlJhYRFz6fqxeRL1sl5Ogsed7A==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-wrap-function": "^7.10.4", + "@babel/types": "^7.12.1" + } + }, + "@babel/helper-replace-supers": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.11.tgz", + "integrity": "sha512-q+w1cqmhL7R0FNzth/PLLp2N+scXEK/L2AHbXUyydxp828F4FEa5WcVoqui9vFRiHDQErj9Zof8azP32uGVTRA==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.12.7", + "@babel/helper-optimise-call-expression": "^7.12.10", + "@babel/traverse": "^7.12.10", + "@babel/types": "^7.12.11" + } + }, + "@babel/helper-simple-access": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz", + "integrity": "sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA==", + "dev": true, + "requires": { + "@babel/types": "^7.12.1" + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz", + "integrity": "sha512-Mf5AUuhG1/OCChOJ/HcADmvcHM42WJockombn8ATJG3OnyiSxBK/Mm5x78BQWvmtXZKHgbjdGL2kin/HOLlZGA==", + "dev": true, + "requires": { + "@babel/types": "^7.12.1" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz", + "integrity": "sha512-LsIVN8j48gHgwzfocYUSkO/hjYAOJqlpJEc7tGXcIm4cubjVUf8LGW6eWRyxEu7gA25q02p0rQUWoCI33HNS5g==", + "dev": true, + "requires": { + "@babel/types": "^7.12.11" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.11.tgz", + "integrity": "sha512-TBFCyj939mFSdeX7U7DDj32WtzYY7fDcalgq8v3fBZMNOJQNn7nOYzMaUCiPxPYfCup69mtIpqlKgMZLvQ8Xhw==", + "dev": true + }, + "@babel/helper-wrap-function": { + "version": "7.12.3", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.12.3.tgz", + "integrity": "sha512-Cvb8IuJDln3rs6tzjW3Y8UeelAOdnpB8xtQ4sme2MSZ9wOxrbThporC0y/EtE16VAtoyEfLM404Xr1e0OOp+ow==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helpers": { + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.5.tgz", + "integrity": "sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA==", + "dev": true, + "requires": { + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.12.5", + "@babel/types": "^7.12.5" + } + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.11.tgz", + "integrity": "sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg==", + "dev": true + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.12.tgz", + "integrity": "sha512-nrz9y0a4xmUrRq51bYkWJIO5SBZyG2ys2qinHsN0zHDHVsUaModrkpyWWWXfGqYQmOL3x9sQIcTNN/pBGpo09A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-remap-async-to-generator": "^7.12.1", + "@babel/plugin-syntax-async-generators": "^7.8.0" + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz", + "integrity": "sha512-cKp3dlQsFsEs5CWKnN7BnSHOd0EOW8EKpEjkoz1pO2E5KzIDNV9Ros1b0CnmbVgAGXJubOYVBOGCT1OmJwOI7w==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-proposal-dynamic-import": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.1.tgz", + "integrity": "sha512-a4rhUSZFuq5W8/OO8H7BL5zspjnc1FLd9hlOxIK/f7qG4a0qsqk8uvF/ywgBA8/OmjsapjpvaEOYItfGG1qIvQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-dynamic-import": "^7.8.0" + } + }, + "@babel/plugin-proposal-export-namespace-from": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.12.1.tgz", + "integrity": "sha512-6CThGf0irEkzujYS5LQcjBx8j/4aQGiVv7J9+2f7pGfxqyKh3WnmVJYW3hdrQjyksErMGBPQrCnHfOtna+WLbw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.12.1.tgz", + "integrity": "sha512-GoLDUi6U9ZLzlSda2Df++VSqDJg3CG+dR0+iWsv6XRw1rEq+zwt4DirM9yrxW6XWaTpmai1cWJLMfM8qQJf+yw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.0" + } + }, + "@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.12.1.tgz", + "integrity": "sha512-k8ZmVv0JU+4gcUGeCDZOGd0lCIamU/sMtIiX3UWnUc5yzgq6YUGyEolNYD+MLYKfSzgECPcqetVcJP9Afe/aCA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.12.1.tgz", + "integrity": "sha512-nZY0ESiaQDI1y96+jk6VxMOaL4LPo/QDHBqL+SF3/vl6dHkTwHlOI8L4ZwuRBHgakRBw5zsVylel7QPbbGuYgg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" + } + }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.7.tgz", + "integrity": "sha512-8c+uy0qmnRTeukiGsjLGy6uVs/TFjJchGXUeBqlG4VWYOdJWkhhVPdQ3uHwbmalfJwv2JsV0qffXP4asRfL2SQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz", + "integrity": "sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-transform-parameters": "^7.12.1" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.12.1.tgz", + "integrity": "sha512-hFvIjgprh9mMw5v42sJWLI1lzU5L2sznP805zeT6rySVRA0Y18StRhDqhSxlap0oVgItRsB6WSROp4YnJTJz0g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" + } + }, + "@babel/plugin-proposal-optional-chaining": { + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.7.tgz", + "integrity": "sha512-4ovylXZ0PWmwoOvhU2vhnzVNnm88/Sm9nx7V8BPgMvAzn5zDou3/Awy0EjglyubVHasJj+XCEkr/r1X3P5elCA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-skip-transparent-expression-wrappers": "^7.12.1", + "@babel/plugin-syntax-optional-chaining": "^7.8.0" + } + }, + "@babel/plugin-proposal-private-methods": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.12.1.tgz", + "integrity": "sha512-mwZ1phvH7/NHK6Kf8LP7MYDogGV+DKB1mryFOEwx5EBNQrosvIczzZFTUmWaeujd5xT6G1ELYWUz3CutMhjE1w==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.1.tgz", + "integrity": "sha512-MYq+l+PvHuw/rKUz1at/vb6nCnQ2gmJBNaM62z0OgH7B2W1D9pvkpYtlti9bGtizNIU1K3zm4bZF9F91efVY0w==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.1.tgz", + "integrity": "sha512-U40A76x5gTwmESz+qiqssqmeEsKvcSyvtgktrm0uzcARAmM9I1jR221f6Oq+GmHrcD+LvZDag1UTOTe2fL3TeA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz", + "integrity": "sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.1.tgz", + "integrity": "sha512-i7ooMZFS+a/Om0crxZodrTzNEPJHZrlMVGMTEpFAj6rYY/bKCddB0Dk/YxfPuYXOopuhKk/e1jV6h+WUU9XN3A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.12.1.tgz", + "integrity": "sha512-5QB50qyN44fzzz4/qxDPQMBCTHgxg3n0xRBLJUmBlLoU/sFvxVWGZF/ZUfMVDQuJUKXaBhbupxIzIfZ6Fwk/0A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.12.1.tgz", + "integrity": "sha512-SDtqoEcarK1DFlRJ1hHRY5HvJUj5kX4qmtpMAm2QnhOlyuMC4TMdCRgW6WXpv93rZeYNeLP22y8Aq2dbcDRM1A==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-remap-async-to-generator": "^7.12.1" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.12.1.tgz", + "integrity": "sha512-5OpxfuYnSgPalRpo8EWGPzIYf0lHBWORCkj5M0oLBwHdlux9Ri36QqGW3/LR13RSVOAoUUMzoPI/jpE4ABcHoA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.12.tgz", + "integrity": "sha512-VOEPQ/ExOVqbukuP7BYJtI5ZxxsmegTwzZ04j1aF0dkSypGo9XpDHuOrABsJu+ie+penpSJheDJ11x1BEZNiyQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.12.1.tgz", + "integrity": "sha512-/74xkA7bVdzQTBeSUhLLJgYIcxw/dpEpCdRDiHgPJ3Mv6uC11UhjpOhl72CgqbBCmt1qtssCyB2xnJm1+PFjog==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-define-map": "^7.10.4", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.12.1", + "@babel/helper-split-export-declaration": "^7.10.4", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.12.1.tgz", + "integrity": "sha512-vVUOYpPWB7BkgUWPo4C44mUQHpTZXakEqFjbv8rQMg7TC6S6ZhGZ3otQcRH6u7+adSlE5i0sp63eMC/XGffrzg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.12.1.tgz", + "integrity": "sha512-fRMYFKuzi/rSiYb2uRLiUENJOKq4Gnl+6qOv5f8z0TZXg3llUwUhsNNwrwaT/6dUhJTzNpBr+CUvEWBtfNY1cw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.12.1.tgz", + "integrity": "sha512-B2pXeRKoLszfEW7J4Hg9LoFaWEbr/kzo3teWHmtFCszjRNa/b40f9mfeqZsIDLLt/FjwQ6pz/Gdlwy85xNckBA==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.12.1.tgz", + "integrity": "sha512-iRght0T0HztAb/CazveUpUQrZY+aGKKaWXMJ4uf9YJtqxSUe09j3wteztCUDRHs+SRAL7yMuFqUsLoAKKzgXjw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.12.1.tgz", + "integrity": "sha512-7tqwy2bv48q+c1EHbXK0Zx3KXd2RVQp6OC7PbwFNt/dPTAV3Lu5sWtWuAj8owr5wqtWnqHfl2/mJlUmqkChKug==", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.12.1.tgz", + "integrity": "sha512-Zaeq10naAsuHo7heQvyV0ptj4dlZJwZgNAtBYBnu5nNKJoW62m0zKcIEyVECrUKErkUkg6ajMy4ZfnVZciSBhg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.12.1.tgz", + "integrity": "sha512-JF3UgJUILoFrFMEnOJLJkRHSk6LUSXLmEFsA23aR2O5CSLUxbeUX1IZ1YQ7Sn0aXb601Ncwjx73a+FVqgcljVw==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.12.1.tgz", + "integrity": "sha512-+PxVGA+2Ag6uGgL0A5f+9rklOnnMccwEBzwYFL3EUaKuiyVnUipyXncFcfjSkbimLrODoqki1U9XxZzTvfN7IQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.12.1.tgz", + "integrity": "sha512-1sxePl6z9ad0gFMB9KqmYofk34flq62aqMt9NqliS/7hPEpURUCMbyHXrMPlo282iY7nAvUB1aQd5mg79UD9Jg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.12.1.tgz", + "integrity": "sha512-tDW8hMkzad5oDtzsB70HIQQRBiTKrhfgwC/KkJeGsaNFTdWhKNt/BiE8c5yj19XiGyrxpbkOfH87qkNg1YGlOQ==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.12.1.tgz", + "integrity": "sha512-dY789wq6l0uLY8py9c1B48V8mVL5gZh/+PQ5ZPrylPYsnAvnEMjqsUXkuoDVPeVK+0VyGar+D08107LzDQ6pag==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-simple-access": "^7.12.1", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.12.1.tgz", + "integrity": "sha512-Hn7cVvOavVh8yvW6fLwveFqSnd7rbQN3zJvoPNyNaQSvgfKmDBO9U1YL9+PCXGRlZD9tNdWTy5ACKqMuzyn32Q==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.10.4", + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-validator-identifier": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.12.1.tgz", + "integrity": "sha512-aEIubCS0KHKM0zUos5fIoQm+AZUMt1ZvMpqz0/H5qAQ7vWylr9+PLYurT+Ic7ID/bKLd4q8hDovaG3Zch2uz5Q==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.12.1.tgz", + "integrity": "sha512-tB43uQ62RHcoDp9v2Nsf+dSM8sbNodbEicbQNA53zHz8pWUhsgHSJCGpt7daXxRydjb0KnfmB+ChXOv3oADp1Q==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.12.1" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.12.1.tgz", + "integrity": "sha512-+eW/VLcUL5L9IvJH7rT1sT0CzkdUTvPrXC2PXTn/7z7tXLBuKvezYbGdxD5WMRoyvyaujOq2fWoKl869heKjhw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.12.1.tgz", + "integrity": "sha512-AvypiGJH9hsquNUn+RXVcBdeE3KHPZexWRdimhuV59cSoOt5kFBmqlByorAeUlGG2CJWd0U+4ZtNKga/TB0cAw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.12.1" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.12.1.tgz", + "integrity": "sha512-xq9C5EQhdPK23ZeCdMxl8bbRnAgHFrw5EOC3KJUsSylZqdkCaFEXxGSBuTSObOpiiHHNyb82es8M1QYgfQGfNg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.12.1.tgz", + "integrity": "sha512-6MTCR/mZ1MQS+AwZLplX4cEySjCpnIF26ToWo942nqn8hXSm7McaHQNeGx/pt7suI1TWOWMfa/NgBhiqSnX0cQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-react-display-name": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.12.1.tgz", + "integrity": "sha512-cAzB+UzBIrekfYxyLlFqf/OagTvHLcVBb5vpouzkYkBclRPraiygVnafvAoipErZLI8ANv8Ecn6E/m5qPXD26w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-react-jsx": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.12.tgz", + "integrity": "sha512-JDWGuzGNWscYcq8oJVCtSE61a5+XAOos+V0HrxnDieUus4UMnBEosDnY1VJqU5iZ4pA04QY7l0+JvHL1hZEfsw==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.12.10", + "@babel/helper-module-imports": "^7.12.5", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-jsx": "^7.12.1", + "@babel/types": "^7.12.12" + } + }, + "@babel/plugin-transform-react-jsx-development": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.12.12.tgz", + "integrity": "sha512-i1AxnKxHeMxUaWVXQOSIco4tvVvvCxMSfeBMnMM06mpaJt3g+MpxYQQrDfojUQldP1xxraPSJYSMEljoWM/dCg==", + "dev": true, + "requires": { + "@babel/plugin-transform-react-jsx": "^7.12.12" + } + }, + "@babel/plugin-transform-react-pure-annotations": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.12.1.tgz", + "integrity": "sha512-RqeaHiwZtphSIUZ5I85PEH19LOSzxfuEazoY7/pWASCAIBuATQzpSVD+eT6MebeeZT2F4eSL0u4vw6n4Nm0Mjg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.12.1.tgz", + "integrity": "sha512-gYrHqs5itw6i4PflFX3OdBPMQdPbF4bj2REIUxlMRUFk0/ZOAIpDFuViuxPjUL7YC8UPnf+XG7/utJvqXdPKng==", + "dev": true, + "requires": { + "regenerator-transform": "^0.14.2" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.12.1.tgz", + "integrity": "sha512-pOnUfhyPKvZpVyBHhSBoX8vfA09b7r00Pmm1sH+29ae2hMTKVmSp4Ztsr8KBKjLjx17H0eJqaRC3bR2iThM54A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.1.tgz", + "integrity": "sha512-GFZS3c/MhX1OusqB1MZ1ct2xRzX5ppQh2JU1h2Pnfk88HtFTM+TWQqJNfwkmxtPQtb/s1tk87oENfXJlx7rSDw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.12.1.tgz", + "integrity": "sha512-vuLp8CP0BE18zVYjsEBZ5xoCecMK6LBMMxYzJnh01rxQRvhNhH1csMMmBfNo5tGpGO+NhdSNW2mzIvBu3K1fng==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-skip-transparent-expression-wrappers": "^7.12.1" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.7.tgz", + "integrity": "sha512-VEiqZL5N/QvDbdjfYQBhruN0HYjSPjC4XkeqW4ny/jNtH9gcbgaqBIXYEZCNnESMAGs0/K/R7oFGMhOyu/eIxg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.12.1.tgz", + "integrity": "sha512-b4Zx3KHi+taXB1dVRBhVJtEPi9h1THCeKmae2qP0YdUHIFhVjtpqqNfxeVAa1xeHVhAy4SbHxEwx5cltAu5apw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.10.tgz", + "integrity": "sha512-JQ6H8Rnsogh//ijxspCjc21YPd3VLVoYtAwv3zQmqAt8YGYUtdo5usNhdl4b9/Vir2kPFZl6n1h0PfUz4hJhaA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.12.1.tgz", + "integrity": "sha512-I8gNHJLIc7GdApm7wkVnStWssPNbSRMPtgHdmH3sRM1zopz09UWPS4x5V4n1yz/MIWTVnJ9sp6IkuXdWM4w+2Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.1.tgz", + "integrity": "sha512-SqH4ClNngh/zGwHZOOQMTD+e8FGWexILV+ePMyiDJttAWRh5dhDL8rcl5lSgU3Huiq6Zn6pWTMvdPAb21Dwdyg==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/preset-env": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.12.11.tgz", + "integrity": "sha512-j8Tb+KKIXKYlDBQyIOy4BLxzv1NUOwlHfZ74rvW+Z0Gp4/cI2IMDPBWAgWceGcE7aep9oL/0K9mlzlMGxA8yNw==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.12.7", + "@babel/helper-compilation-targets": "^7.12.5", + "@babel/helper-module-imports": "^7.12.5", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-validator-option": "^7.12.11", + "@babel/plugin-proposal-async-generator-functions": "^7.12.1", + "@babel/plugin-proposal-class-properties": "^7.12.1", + "@babel/plugin-proposal-dynamic-import": "^7.12.1", + "@babel/plugin-proposal-export-namespace-from": "^7.12.1", + "@babel/plugin-proposal-json-strings": "^7.12.1", + "@babel/plugin-proposal-logical-assignment-operators": "^7.12.1", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1", + "@babel/plugin-proposal-numeric-separator": "^7.12.7", + "@babel/plugin-proposal-object-rest-spread": "^7.12.1", + "@babel/plugin-proposal-optional-catch-binding": "^7.12.1", + "@babel/plugin-proposal-optional-chaining": "^7.12.7", + "@babel/plugin-proposal-private-methods": "^7.12.1", + "@babel/plugin-proposal-unicode-property-regex": "^7.12.1", + "@babel/plugin-syntax-async-generators": "^7.8.0", + "@babel/plugin-syntax-class-properties": "^7.12.1", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.0", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.0", + "@babel/plugin-syntax-top-level-await": "^7.12.1", + "@babel/plugin-transform-arrow-functions": "^7.12.1", + "@babel/plugin-transform-async-to-generator": "^7.12.1", + "@babel/plugin-transform-block-scoped-functions": "^7.12.1", + "@babel/plugin-transform-block-scoping": "^7.12.11", + "@babel/plugin-transform-classes": "^7.12.1", + "@babel/plugin-transform-computed-properties": "^7.12.1", + "@babel/plugin-transform-destructuring": "^7.12.1", + "@babel/plugin-transform-dotall-regex": "^7.12.1", + "@babel/plugin-transform-duplicate-keys": "^7.12.1", + "@babel/plugin-transform-exponentiation-operator": "^7.12.1", + "@babel/plugin-transform-for-of": "^7.12.1", + "@babel/plugin-transform-function-name": "^7.12.1", + "@babel/plugin-transform-literals": "^7.12.1", + "@babel/plugin-transform-member-expression-literals": "^7.12.1", + "@babel/plugin-transform-modules-amd": "^7.12.1", + "@babel/plugin-transform-modules-commonjs": "^7.12.1", + "@babel/plugin-transform-modules-systemjs": "^7.12.1", + "@babel/plugin-transform-modules-umd": "^7.12.1", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.12.1", + "@babel/plugin-transform-new-target": "^7.12.1", + "@babel/plugin-transform-object-super": "^7.12.1", + "@babel/plugin-transform-parameters": "^7.12.1", + "@babel/plugin-transform-property-literals": "^7.12.1", + "@babel/plugin-transform-regenerator": "^7.12.1", + "@babel/plugin-transform-reserved-words": "^7.12.1", + "@babel/plugin-transform-shorthand-properties": "^7.12.1", + "@babel/plugin-transform-spread": "^7.12.1", + "@babel/plugin-transform-sticky-regex": "^7.12.7", + "@babel/plugin-transform-template-literals": "^7.12.1", + "@babel/plugin-transform-typeof-symbol": "^7.12.10", + "@babel/plugin-transform-unicode-escapes": "^7.12.1", + "@babel/plugin-transform-unicode-regex": "^7.12.1", + "@babel/preset-modules": "^0.1.3", + "@babel/types": "^7.12.11", + "core-js-compat": "^3.8.0", + "semver": "^5.5.0" + } + }, + "@babel/preset-modules": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz", + "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + } + }, + "@babel/preset-react": { + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.12.10.tgz", + "integrity": "sha512-vtQNjaHRl4DUpp+t+g4wvTHsLQuye+n0H/wsXIZRn69oz/fvNC7gQ4IK73zGJBaxvHoxElDvnYCthMcT7uzFoQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-transform-react-display-name": "^7.12.1", + "@babel/plugin-transform-react-jsx": "^7.12.10", + "@babel/plugin-transform-react-jsx-development": "^7.12.7", + "@babel/plugin-transform-react-pure-annotations": "^7.12.1" + } + }, + "@babel/runtime": { + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz", + "integrity": "sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/template": { + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.7.tgz", + "integrity": "sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.12.7", + "@babel/types": "^7.12.7" + } + }, + "@babel/traverse": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.12.tgz", + "integrity": "sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.11", + "@babel/generator": "^7.12.11", + "@babel/helper-function-name": "^7.12.11", + "@babel/helper-split-export-declaration": "^7.12.11", + "@babel/parser": "^7.12.11", + "@babel/types": "^7.12.12", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.19" + } + }, + "@babel/types": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", + "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "@discoveryjs/json-ext": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz", + "integrity": "sha512-HyYEUDeIj5rRQU2Hk5HTB2uHsbRQpF70nvMhVzi+VJR0X+xNEhjPui4/kBf3VeH/wqD28PT4sVOm8qqLjBrSZg==", + "dev": true + }, + "@nodelib/fs.scandir": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", + "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.4", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", + "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", + "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.4", + "fastq": "^1.6.0" + } + }, + "@npmcli/move-file": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.0.1.tgz", + "integrity": "sha512-Uv6h1sT+0DrblvIrolFtbvM1FgWm+/sy4B3pvLp67Zys+thcukzS5ekn7HsZFGpWP4Q3fYJCljbWQE/XivMRLw==", + "dev": true, + "requires": { + "mkdirp": "^1.0.4" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + } + } + }, + "@types/anymatch": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz", + "integrity": "sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==", + "dev": true + }, + "@types/eslint": { + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.2.6.tgz", + "integrity": "sha512-I+1sYH+NPQ3/tVqCeUSBwTE/0heyvtXqpIopUUArlBm0Kpocb8FbMa3AZ/ASKIFpN3rnEx932TTXDbt9OXsNDw==", + "dev": true, + "requires": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "@types/eslint-scope": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.0.tgz", + "integrity": "sha512-O/ql2+rrCUe2W2rs7wMR+GqPRcgB6UiqN5RhrR5xruFlY7l9YLMn0ZkDzjoHLeiFkR8MCQZVudUuuvQ2BLC9Qw==", + "dev": true, + "requires": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "@types/estree": { + "version": "0.0.45", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.45.tgz", + "integrity": "sha512-jnqIUKDUqJbDIUxm0Uj7bnlMnRm1T/eZ9N+AVMqhPgzrba2GhGG5o/jCTwmdPK709nEZsGoMzXEDUjcXHa3W0g==", + "dev": true + }, + "@types/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", + "dev": true, + "requires": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/html-minifier-terser": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", + "integrity": "sha512-giAlZwstKbmvMk1OO7WXSj4OZ0keXAcl2TQq4LWHiiPH2ByaH7WeUzng+Qej8UPxxv+8lRTuouo0iaNDBuzIBA==", + "dev": true + }, + "@types/json-schema": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", + "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==", + "dev": true + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, + "@types/node": { + "version": "14.14.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.20.tgz", + "integrity": "sha512-Y93R97Ouif9JEOWPIUyU+eyIdyRqQR0I8Ez1dzku4hDx34NWh4HbtIc3WNzwB1Y9ULvNGeu5B8h8bVL5cAk4/A==", + "dev": true + }, + "@types/source-list-map": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", + "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", + "dev": true + }, + "@types/tapable": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.6.tgz", + "integrity": "sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA==", + "dev": true + }, + "@types/uglify-js": { + "version": "3.11.1", + "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.11.1.tgz", + "integrity": "sha512-7npvPKV+jINLu1SpSYVWG8KvyJBhBa8tmzMMdDoVc2pWUYHN8KIXlPJhjJ4LT97c4dXJA2SHL/q6ADbDriZN+Q==", + "dev": true, + "requires": { + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "@types/webpack": { + "version": "4.41.25", + "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.25.tgz", + "integrity": "sha512-cr6kZ+4m9lp86ytQc1jPOJXgINQyz3kLLunZ57jznW+WIAL0JqZbGubQk4GlD42MuQL5JGOABrxdpqqWeovlVQ==", + "dev": true, + "requires": { + "@types/anymatch": "*", + "@types/node": "*", + "@types/tapable": "*", + "@types/uglify-js": "*", + "@types/webpack-sources": "*", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "@types/webpack-sources": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-2.1.0.tgz", + "integrity": "sha512-LXn/oYIpBeucgP1EIJbKQ2/4ZmpvRl+dlrFdX7+94SKRUV3Evy3FsfMZY318vGhkWUS5MPhtOM3w1/hCOAOXcg==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/source-list-map": "*", + "source-map": "^0.7.3" + }, + "dependencies": { + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + } + } + }, + "@typescript-eslint/experimental-utils": { + "version": "2.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.34.0.tgz", + "integrity": "sha512-eS6FTkq+wuMJ+sgtuNTtcqavWXqsflWcfBnlYhg/nS4aZ1leewkXGbvBhaapn1q6qf4M71bsR1tez5JTRMuqwA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/typescript-estree": "2.34.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^2.0.0" + }, + "dependencies": { + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + } + } + }, + "@typescript-eslint/typescript-estree": { + "version": "2.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.34.0.tgz", + "integrity": "sha512-OMAr+nJWKdlVM9LOqCqh3pQQPwxHAN7Du8DR6dmwCrAmxtiXQnhHJ6tBNtf+cggqfo51SG/FCwnKhXCIM7hnVg==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "eslint-visitor-keys": "^1.1.0", + "glob": "^7.1.6", + "is-glob": "^4.0.1", + "lodash": "^4.17.15", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@webassemblyjs/ast": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.0.tgz", + "integrity": "sha512-kX2W49LWsbthrmIRMbQZuQDhGtjyqXfEmmHyEi4XWnSZtPmxY0+3anPIzsnRb45VH/J55zlOfWvZuY47aJZTJg==", + "dev": true, + "requires": { + "@webassemblyjs/helper-numbers": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.0.tgz", + "integrity": "sha512-Q/aVYs/VnPDVYvsCBL/gSgwmfjeCb4LW8+TMrO3cSzJImgv8lxxEPM2JA5jMrivE7LSz3V+PFqtMbls3m1exDA==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.0.tgz", + "integrity": "sha512-baT/va95eXiXb2QflSx95QGT5ClzWpGaa8L7JnJbgzoYeaA27FCvuBXU758l+KXWRndEmUXjP0Q5fibhavIn8w==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.0.tgz", + "integrity": "sha512-u9HPBEl4DS+vA8qLQdEQ6N/eJQ7gT7aNvMIo8AAWvAl/xMrcOSiI2M0MAnMCy3jIFke7bEee/JwdX1nUpCtdyA==", + "dev": true + }, + "@webassemblyjs/helper-numbers": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.0.tgz", + "integrity": "sha512-DhRQKelIj01s5IgdsOJMKLppI+4zpmcMQ3XboFPLwCpSNH6Hqo1ritgHgD0nqHeSYqofA6aBN/NmXuGjM1jEfQ==", + "dev": true, + "requires": { + "@webassemblyjs/floating-point-hex-parser": "1.11.0", + "@webassemblyjs/helper-api-error": "1.11.0", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.0.tgz", + "integrity": "sha512-MbmhvxXExm542tWREgSFnOVo07fDpsBJg3sIl6fSp9xuu75eGz5lz31q7wTLffwL3Za7XNRCMZy210+tnsUSEA==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.0.tgz", + "integrity": "sha512-3Eb88hcbfY/FCukrg6i3EH8H2UsD7x8Vy47iVJrP967A9JGqgBVL9aH71SETPx1JrGsOUVLo0c7vMCN22ytJew==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-buffer": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0", + "@webassemblyjs/wasm-gen": "1.11.0" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.0.tgz", + "integrity": "sha512-KXzOqpcYQwAfeQ6WbF6HXo+0udBNmw0iXDmEK5sFlmQdmND+tr773Ti8/5T/M6Tl/413ArSJErATd8In3B+WBA==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.0.tgz", + "integrity": "sha512-aqbsHa1mSQAbeeNcl38un6qVY++hh8OpCOzxhixSYgbRfNWcxJNJQwe2rezK9XEcssJbbWIkblaJRwGMS9zp+g==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.0.tgz", + "integrity": "sha512-A/lclGxH6SpSLSyFowMzO/+aDEPU4hvEiooCMXQPcQFPPJaYcPQNKGOCLUySJsYJ4trbpr+Fs08n4jelkVTGVw==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.0.tgz", + "integrity": "sha512-JHQ0damXy0G6J9ucyKVXO2j08JVJ2ntkdJlq1UTiUrIgfGMmA7Ik5VdC/L8hBK46kVJgujkBIoMtT8yVr+yVOQ==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-buffer": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0", + "@webassemblyjs/helper-wasm-section": "1.11.0", + "@webassemblyjs/wasm-gen": "1.11.0", + "@webassemblyjs/wasm-opt": "1.11.0", + "@webassemblyjs/wasm-parser": "1.11.0", + "@webassemblyjs/wast-printer": "1.11.0" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.0.tgz", + "integrity": "sha512-BEUv1aj0WptCZ9kIS30th5ILASUnAPEvE3tVMTrItnZRT9tXCLW2LEXT8ezLw59rqPP9klh9LPmpU+WmRQmCPQ==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0", + "@webassemblyjs/ieee754": "1.11.0", + "@webassemblyjs/leb128": "1.11.0", + "@webassemblyjs/utf8": "1.11.0" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.0.tgz", + "integrity": "sha512-tHUSP5F4ywyh3hZ0+fDQuWxKx3mJiPeFufg+9gwTpYp324mPCQgnuVKwzLTZVqj0duRDovnPaZqDwoyhIO8kYg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-buffer": "1.11.0", + "@webassemblyjs/wasm-gen": "1.11.0", + "@webassemblyjs/wasm-parser": "1.11.0" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.0.tgz", + "integrity": "sha512-6L285Sgu9gphrcpDXINvm0M9BskznnzJTE7gYkjDbxET28shDqp27wpruyx3C2S/dvEwiigBwLA1cz7lNUi0kw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-api-error": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0", + "@webassemblyjs/ieee754": "1.11.0", + "@webassemblyjs/leb128": "1.11.0", + "@webassemblyjs/utf8": "1.11.0" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.0.tgz", + "integrity": "sha512-Fg5OX46pRdTgB7rKIUojkh9vXaVN6sGYCnEiJN1GYkb0RPwShZXp6KTDqmoMdQPKhcroOXh3fEzmkWmCYaKYhQ==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.0", + "@xtuc/long": "4.2.2" + } + }, + "@webpack-cli/info": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.2.1.tgz", + "integrity": "sha512-fLnDML5HZ5AEKzHul8xLAksoKN2cibu6MgonkUj8R9V7bbeVRkd1XbGEGWrAUNYHbX1jcqCsDEpBviE5StPMzQ==", + "dev": true, + "requires": { + "envinfo": "^7.7.3" + } + }, + "@webpack-cli/serve": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.2.1.tgz", + "integrity": "sha512-Zj1z6AyS+vqV6Hfi7ngCjFGdHV5EwZNIHo6QfFTNe9PyW+zBU1zJ9BiOW1pmUEq950RC4+Dym6flyA/61/vhyw==", + "dev": true + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "dev": true + }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "dev": true + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true + }, + "ansi-colors": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", + "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", + "dev": true + }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-html": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", + "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", + "dev": true + }, + "array-includes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.2.tgz", + "integrity": "sha512-w2GspexNQpx+PutG3QpT437/BenZBj0M/MZGn5mzv/MofYqo0xmRHzn4lFsoDlWJ+THYsGJmFlW68WlDFx7VRw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "get-intrinsic": "^1.0.1", + "is-string": "^1.0.5" + } + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "array.prototype.flatmap": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.4.tgz", + "integrity": "sha512-r9Z0zYoxqHz60vvQbWEdXIEtCwHF0yxaWfno9qzXeNHvfyl3BZqygmGzb84dsubyaXLH4husF+NFgMSdpZhk2Q==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "function-bind": "^1.1.1" + } + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "ast-types": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.9.6.tgz", + "integrity": "sha1-ECyenpAF0+fjgpvwxPok7oYu6bk=", + "dev": true + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "awesome-typescript-loader": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/awesome-typescript-loader/-/awesome-typescript-loader-5.2.1.tgz", + "integrity": "sha512-slv66OAJB8orL+UUaTI3pKlLorwIvS4ARZzYR9iJJyGsEgOqueMfOMdKySWzZ73vIkEe3fcwFgsKMg4d8zyb1g==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "enhanced-resolve": "^4.0.0", + "loader-utils": "^1.1.0", + "lodash": "^4.17.5", + "micromatch": "^3.1.9", + "mkdirp": "^0.5.1", + "source-map-support": "^0.5.3", + "webpack-log": "^1.2.0" + } + }, + "axios": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", + "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", + "requires": { + "follow-redirects": "^1.10.0" + } + }, + "babel-eslint": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", + "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.7.0", + "@babel/traverse": "^7.7.0", + "@babel/types": "^7.7.0", + "eslint-visitor-keys": "^1.0.0", + "resolve": "^1.12.0" + } + }, + "babel-helper-evaluate-path": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-helper-evaluate-path/-/babel-helper-evaluate-path-0.5.0.tgz", + "integrity": "sha512-mUh0UhS607bGh5wUMAQfOpt2JX2ThXMtppHRdRU1kL7ZLRWIXxoV2UIV1r2cAeeNeU1M5SB5/RSUgUxrK8yOkA==", + "dev": true + }, + "babel-helper-flip-expressions": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-helper-flip-expressions/-/babel-helper-flip-expressions-0.4.3.tgz", + "integrity": "sha1-NpZzahKKwYvCUlS19AoizrPB0/0=", + "dev": true + }, + "babel-helper-is-nodes-equiv": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/babel-helper-is-nodes-equiv/-/babel-helper-is-nodes-equiv-0.0.1.tgz", + "integrity": "sha1-NOmzALFHnd2Y7HfqC76TQt/jloQ=", + "dev": true + }, + "babel-helper-is-void-0": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-helper-is-void-0/-/babel-helper-is-void-0-0.4.3.tgz", + "integrity": "sha1-fZwBtFYee5Xb2g9u7kj1tg5nMT4=", + "dev": true + }, + "babel-helper-mark-eval-scopes": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-helper-mark-eval-scopes/-/babel-helper-mark-eval-scopes-0.4.3.tgz", + "integrity": "sha1-0kSjvvmESHJgP/tG4izorN9VFWI=", + "dev": true + }, + "babel-helper-remove-or-void": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-helper-remove-or-void/-/babel-helper-remove-or-void-0.4.3.tgz", + "integrity": "sha1-pPA7QAd6D/6I5F0HAQ3uJB/1rmA=", + "dev": true + }, + "babel-helper-to-multiple-sequence-expressions": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-helper-to-multiple-sequence-expressions/-/babel-helper-to-multiple-sequence-expressions-0.5.0.tgz", + "integrity": "sha512-m2CvfDW4+1qfDdsrtf4dwOslQC3yhbgyBFptncp4wvtdrDHqueW7slsYv4gArie056phvQFhT2nRcGS4bnm6mA==", + "dev": true + }, + "babel-loader": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.2.tgz", + "integrity": "sha512-JvTd0/D889PQBtUXJ2PXaKU/pjZDMtHA9V2ecm+eNRmmBCMR09a+fmpGTNwnJtFmFl5Ei7Vy47LjBb+L0wQ99g==", + "dev": true, + "requires": { + "find-cache-dir": "^3.3.1", + "loader-utils": "^1.4.0", + "make-dir": "^3.1.0", + "schema-utils": "^2.6.5" + } + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "dev": true, + "requires": { + "object.assign": "^4.1.0" + } + }, + "babel-plugin-minify-builtins": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-builtins/-/babel-plugin-minify-builtins-0.5.0.tgz", + "integrity": "sha512-wpqbN7Ov5hsNwGdzuzvFcjgRlzbIeVv1gMIlICbPj0xkexnfoIDe7q+AZHMkQmAE/F9R5jkrB6TLfTegImlXag==", + "dev": true + }, + "babel-plugin-minify-constant-folding": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-constant-folding/-/babel-plugin-minify-constant-folding-0.5.0.tgz", + "integrity": "sha512-Vj97CTn/lE9hR1D+jKUeHfNy+m1baNiJ1wJvoGyOBUx7F7kJqDZxr9nCHjO/Ad+irbR3HzR6jABpSSA29QsrXQ==", + "dev": true, + "requires": { + "babel-helper-evaluate-path": "^0.5.0" + } + }, + "babel-plugin-minify-dead-code-elimination": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-dead-code-elimination/-/babel-plugin-minify-dead-code-elimination-0.5.1.tgz", + "integrity": "sha512-x8OJOZIrRmQBcSqxBcLbMIK8uPmTvNWPXH2bh5MDCW1latEqYiRMuUkPImKcfpo59pTUB2FT7HfcgtG8ZlR5Qg==", + "dev": true, + "requires": { + "babel-helper-evaluate-path": "^0.5.0", + "babel-helper-mark-eval-scopes": "^0.4.3", + "babel-helper-remove-or-void": "^0.4.3", + "lodash": "^4.17.11" + } + }, + "babel-plugin-minify-flip-comparisons": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-flip-comparisons/-/babel-plugin-minify-flip-comparisons-0.4.3.tgz", + "integrity": "sha1-AMqHDLjxO0XAOLPB68DyJyk8llo=", + "dev": true, + "requires": { + "babel-helper-is-void-0": "^0.4.3" + } + }, + "babel-plugin-minify-guarded-expressions": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-guarded-expressions/-/babel-plugin-minify-guarded-expressions-0.4.4.tgz", + "integrity": "sha512-RMv0tM72YuPPfLT9QLr3ix9nwUIq+sHT6z8Iu3sLbqldzC1Dls8DPCywzUIzkTx9Zh1hWX4q/m9BPoPed9GOfA==", + "dev": true, + "requires": { + "babel-helper-evaluate-path": "^0.5.0", + "babel-helper-flip-expressions": "^0.4.3" + } + }, + "babel-plugin-minify-infinity": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-infinity/-/babel-plugin-minify-infinity-0.4.3.tgz", + "integrity": "sha1-37h2obCKBldjhO8/kuZTumB7Oco=", + "dev": true + }, + "babel-plugin-minify-mangle-names": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-mangle-names/-/babel-plugin-minify-mangle-names-0.5.0.tgz", + "integrity": "sha512-3jdNv6hCAw6fsX1p2wBGPfWuK69sfOjfd3zjUXkbq8McbohWy23tpXfy5RnToYWggvqzuMOwlId1PhyHOfgnGw==", + "dev": true, + "requires": { + "babel-helper-mark-eval-scopes": "^0.4.3" + } + }, + "babel-plugin-minify-numeric-literals": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-numeric-literals/-/babel-plugin-minify-numeric-literals-0.4.3.tgz", + "integrity": "sha1-jk/VYcefeAEob/YOjF/Z3u6TwLw=", + "dev": true + }, + "babel-plugin-minify-replace": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-replace/-/babel-plugin-minify-replace-0.5.0.tgz", + "integrity": "sha512-aXZiaqWDNUbyNNNpWs/8NyST+oU7QTpK7J9zFEFSA0eOmtUNMU3fczlTTTlnCxHmq/jYNFEmkkSG3DDBtW3Y4Q==", + "dev": true + }, + "babel-plugin-minify-simplify": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-simplify/-/babel-plugin-minify-simplify-0.5.1.tgz", + "integrity": "sha512-OSYDSnoCxP2cYDMk9gxNAed6uJDiDz65zgL6h8d3tm8qXIagWGMLWhqysT6DY3Vs7Fgq7YUDcjOomhVUb+xX6A==", + "dev": true, + "requires": { + "babel-helper-evaluate-path": "^0.5.0", + "babel-helper-flip-expressions": "^0.4.3", + "babel-helper-is-nodes-equiv": "^0.0.1", + "babel-helper-to-multiple-sequence-expressions": "^0.5.0" + } + }, + "babel-plugin-minify-type-constructors": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-type-constructors/-/babel-plugin-minify-type-constructors-0.4.3.tgz", + "integrity": "sha1-G8bxW4f3qxCF1CszC3F2V6IVZQA=", + "dev": true, + "requires": { + "babel-helper-is-void-0": "^0.4.3" + } + }, + "babel-plugin-module-resolver": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-4.1.0.tgz", + "integrity": "sha512-MlX10UDheRr3lb3P0WcaIdtCSRlxdQsB1sBqL7W0raF070bGl1HQQq5K3T2vf2XAYie+ww+5AKC/WrkjRO2knA==", + "dev": true, + "requires": { + "find-babel-config": "^1.2.0", + "glob": "^7.1.6", + "pkg-up": "^3.1.0", + "reselect": "^4.0.0", + "resolve": "^1.13.1" + } + }, + "babel-plugin-transform-inline-consecutive-adds": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-inline-consecutive-adds/-/babel-plugin-transform-inline-consecutive-adds-0.4.3.tgz", + "integrity": "sha1-Mj1Ho+pjqDp6w8gRro5pQfrysNE=", + "dev": true + }, + "babel-plugin-transform-member-expression-literals": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-member-expression-literals/-/babel-plugin-transform-member-expression-literals-6.9.4.tgz", + "integrity": "sha1-NwOcmgwzE6OUlfqsL/OmtbnQOL8=", + "dev": true + }, + "babel-plugin-transform-merge-sibling-variables": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-merge-sibling-variables/-/babel-plugin-transform-merge-sibling-variables-6.9.4.tgz", + "integrity": "sha1-hbQi/DN3tEnJ0c3kQIcgNTJAHa4=", + "dev": true + }, + "babel-plugin-transform-minify-booleans": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-minify-booleans/-/babel-plugin-transform-minify-booleans-6.9.4.tgz", + "integrity": "sha1-rLs+VqNVXdI5KOS1gtKFFi3SsZg=", + "dev": true + }, + "babel-plugin-transform-property-literals": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.9.4.tgz", + "integrity": "sha1-mMHSHiVXNlc/k+zlRFn2ziSYXTk=", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "babel-plugin-transform-regexp-constructors": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regexp-constructors/-/babel-plugin-transform-regexp-constructors-0.4.3.tgz", + "integrity": "sha1-WLd3W2OvzzMyj66aX4j71PsLSWU=", + "dev": true + }, + "babel-plugin-transform-remove-console": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-console/-/babel-plugin-transform-remove-console-6.9.4.tgz", + "integrity": "sha1-uYA2DAZzhOJLNXpYjYB9PINSd4A=", + "dev": true + }, + "babel-plugin-transform-remove-debugger": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-debugger/-/babel-plugin-transform-remove-debugger-6.9.4.tgz", + "integrity": "sha1-QrcnYxyXl44estGZp67IShgznvI=", + "dev": true + }, + "babel-plugin-transform-remove-undefined": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-undefined/-/babel-plugin-transform-remove-undefined-0.5.0.tgz", + "integrity": "sha512-+M7fJYFaEE/M9CXa0/IRkDbiV3wRELzA1kKQFCJ4ifhrzLKn/9VCCgj9OFmYWwBd8IB48YdgPkHYtbYq+4vtHQ==", + "dev": true, + "requires": { + "babel-helper-evaluate-path": "^0.5.0" + } + }, + "babel-plugin-transform-simplify-comparison-operators": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-simplify-comparison-operators/-/babel-plugin-transform-simplify-comparison-operators-6.9.4.tgz", + "integrity": "sha1-9ir+CWyrDh9ootdT/fKDiIRxzrk=", + "dev": true + }, + "babel-plugin-transform-undefined-to-void": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-undefined-to-void/-/babel-plugin-transform-undefined-to-void-6.9.4.tgz", + "integrity": "sha1-viQcqBQEAwZ4t0hxcyK4nQyP4oA=", + "dev": true + }, + "babel-preset-minify": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/babel-preset-minify/-/babel-preset-minify-0.5.1.tgz", + "integrity": "sha512-1IajDumYOAPYImkHbrKeiN5AKKP9iOmRoO2IPbIuVp0j2iuCcj0n7P260z38siKMZZ+85d3mJZdtW8IgOv+Tzg==", + "dev": true, + "requires": { + "babel-plugin-minify-builtins": "^0.5.0", + "babel-plugin-minify-constant-folding": "^0.5.0", + "babel-plugin-minify-dead-code-elimination": "^0.5.1", + "babel-plugin-minify-flip-comparisons": "^0.4.3", + "babel-plugin-minify-guarded-expressions": "^0.4.4", + "babel-plugin-minify-infinity": "^0.4.3", + "babel-plugin-minify-mangle-names": "^0.5.0", + "babel-plugin-minify-numeric-literals": "^0.4.3", + "babel-plugin-minify-replace": "^0.5.0", + "babel-plugin-minify-simplify": "^0.5.1", + "babel-plugin-minify-type-constructors": "^0.4.3", + "babel-plugin-transform-inline-consecutive-adds": "^0.4.3", + "babel-plugin-transform-member-expression-literals": "^6.9.4", + "babel-plugin-transform-merge-sibling-variables": "^6.9.4", + "babel-plugin-transform-minify-booleans": "^6.9.4", + "babel-plugin-transform-property-literals": "^6.9.4", + "babel-plugin-transform-regexp-constructors": "^0.4.3", + "babel-plugin-transform-remove-console": "^6.9.4", + "babel-plugin-transform-remove-debugger": "^6.9.4", + "babel-plugin-transform-remove-undefined": "^0.5.0", + "babel-plugin-transform-simplify-comparison-operators": "^6.9.4", + "babel-plugin-transform-undefined-to-void": "^6.9.4", + "lodash": "^4.17.11" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", + "dev": true + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dev": true, + "requires": { + "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" + }, + "dependencies": { + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", + "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", + "dev": true, + "requires": { + "array-flatten": "^2.1.0", + "deep-equal": "^1.0.1", + "dns-equal": "^1.0.0", + "dns-txt": "^2.0.2", + "multicast-dns": "^6.0.1", + "multicast-dns-service-types": "^1.1.0" + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "browserslist": { + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.1.tgz", + "integrity": "sha512-UXhDrwqsNcpTYJBTZsbGATDxZbiVDsx6UjpmRUmtnP10pr8wAYr5LgFoEFw9ixriQH2mv/NX2SfGzE/o8GndLA==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001173", + "colorette": "^1.2.1", + "electron-to-chromium": "^1.3.634", + "escalade": "^3.1.1", + "node-releases": "^1.1.69" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "buffer-indexof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", + "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", + "dev": true + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "call-bind": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.1.tgz", + "integrity": "sha512-tvAvUwNcRikl3RVF20X9lsYmmepsovzTWeJiXjO0PkJp15uy/6xKFZOQtuiSULwYW+6ToZBprphCgWXC2dSgcQ==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camel-case": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", + "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", + "dev": true, + "requires": { + "no-case": "^2.2.0", + "upper-case": "^1.1.1" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30001174", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001174.tgz", + "integrity": "sha512-tqClL/4ThQq6cfFXH3oJL4rifFBeM6gTkphjao5kgwMaW9yn0tKgQLAEfKzDwj6HQWCB/aWo8kTFlSvIN8geEA==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "dependencies": { + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + } + } + }, + "chrome-trace-event": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", + "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "clean-css": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", + "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==", + "dev": true, + "requires": { + "source-map": "~0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true + }, + "clean-webpack-plugin": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/clean-webpack-plugin/-/clean-webpack-plugin-3.0.0.tgz", + "integrity": "sha512-MciirUH5r+cYLGCOL5JX/ZLzOZbVr1ot3Fw+KcvbhUb6PM+yycqd9ZhIlcigQ5gl+XhppNmw3bEFuaaMNyLj3A==", + "dev": true, + "requires": { + "@types/webpack": "^4.4.31", + "del": "^4.1.1" + } + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-width": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", + "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", + "dev": true + }, + "clipboard-copy": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/clipboard-copy/-/clipboard-copy-3.2.0.tgz", + "integrity": "sha512-vooFaGFL6ulEP1liiaWFBmmfuPm3cY3y7T9eB83ZTnYc/oFeAKsq3NcDrOkBC8XaauEE8zHQwI7k0+JSYiVQSQ==" + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "colorette": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz", + "integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==", + "dev": true + }, + "commander": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "compression-webpack-plugin": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/compression-webpack-plugin/-/compression-webpack-plugin-7.1.2.tgz", + "integrity": "sha512-9DKNW6ILLjx+bNBoviHDgLx6swBhWWH9ApClC9sTH2NoFfQM47BapQfovCm9zjD9v1uZwInF5a925FB9ErGQeQ==", + "dev": true, + "requires": { + "schema-utils": "^3.0.0", + "serialize-javascript": "^5.0.1" + }, + "dependencies": { + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "connect-history-api-fallback": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", + "dev": true + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "dev": true + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "copy-anything": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.1.tgz", + "integrity": "sha512-lA57e7viQHOdPQcrytv5jFeudZZOXuyk47lZym279FiDQ8jeZomXiGuVf6ffMKkJ+3TIai3J1J3yi6M+/4U35g==", + "dev": true, + "requires": { + "is-what": "^3.7.1" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "copy-webpack-plugin": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-6.4.1.tgz", + "integrity": "sha512-MXyPCjdPVx5iiWyl40Va3JGh27bKzOTNY3NjUTrosD2q7dR/cLD0013uqJ3BpFbUjyONINjb6qI7nDIJujrMbA==", + "dev": true, + "requires": { + "cacache": "^15.0.5", + "fast-glob": "^3.2.4", + "find-cache-dir": "^3.3.1", + "glob-parent": "^5.1.1", + "globby": "^11.0.1", + "loader-utils": "^2.0.0", + "normalize-path": "^3.0.0", + "p-limit": "^3.0.2", + "schema-utils": "^3.0.0", + "serialize-javascript": "^5.0.1", + "webpack-sources": "^1.4.3" + }, + "dependencies": { + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "cacache": { + "version": "15.0.5", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.5.tgz", + "integrity": "sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A==", + "dev": true, + "requires": { + "@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.0", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + } + }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true + }, + "globby": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.2.tgz", + "integrity": "sha512-2ZThXDvvV8fYFRVIxnrMQBipZQDr7MxKAmQK1vujaj9/7eF0efG7BPUKJ7jP7G5SLF37xKDXvO4S/KKLj/Z0og==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + } + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "ssri": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.0.tgz", + "integrity": "sha512-aq/pz989nxVYwn16Tsbj1TqFpD5LLrQxHf5zaHuieFV+R0Bbr4y8qUsOA45hXT/N4/9UNXTarBjnjVmjSOVaAA==", + "dev": true, + "requires": { + "minipass": "^3.1.1" + } + } + } + }, + "core-js-compat": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.8.2.tgz", + "integrity": "sha512-LO8uL9lOIyRRrQmZxHZFl1RV+ZbcsAkFWTktn5SmH40WgLtSNYN4m4W2v9ONT147PxBY/XrRhrWq8TlvObyUjQ==", + "dev": true, + "requires": { + "browserslist": "^4.16.0", + "semver": "7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true + } + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "css-loader": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", + "integrity": "sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "cssesc": "^3.0.0", + "icss-utils": "^4.1.1", + "loader-utils": "^1.2.3", + "normalize-path": "^3.0.0", + "postcss": "^7.0.32", + "postcss-modules-extract-imports": "^2.0.0", + "postcss-modules-local-by-default": "^3.0.2", + "postcss-modules-scope": "^2.2.0", + "postcss-modules-values": "^3.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^2.7.0", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "css-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", + "dev": true, + "requires": { + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "css-what": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", + "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==", + "dev": true + }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true + }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "deep-equal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", + "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "dev": true, + "requires": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" + } + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "default-gateway": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", + "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==", + "dev": true, + "requires": { + "execa": "^1.0.0", + "ip-regex": "^2.1.0" + } + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "del": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", + "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "globby": "^6.1.0", + "is-path-cwd": "^2.0.0", + "is-path-in-cwd": "^2.0.0", + "p-map": "^2.0.0", + "pify": "^4.0.1", + "rimraf": "^2.6.3" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "detect-node": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", + "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==", + "dev": true + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", + "dev": true + }, + "dns-packet": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz", + "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==", + "dev": true, + "requires": { + "ip": "^1.1.0", + "safe-buffer": "^5.0.1" + } + }, + "dns-txt": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", + "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", + "dev": true, + "requires": { + "buffer-indexof": "^1.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dev": true, + "requires": { + "utila": "~0.4" + } + }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.1.0.tgz", + "integrity": "sha512-LsTgx/L5VpD+Q8lmsXSHW2WpA+eBlZ9HPf3erD1IoPF00/3JKHZ3BknUVA2QGDNu69ZNmyFmCWBSO45XjYKC5w==", + "dev": true + } + } + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "dev": true, + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + }, + "dependencies": { + "lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "requires": { + "tslib": "^2.0.3" + } + }, + "no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "requires": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", + "dev": true + } + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.635", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.635.tgz", + "integrity": "sha512-RRriZOLs9CpW6KTLmgBqyUdnY0QNqqWs0HOtuQGGEMizOTNNn1P7sGRBxARnUeLejOsgwjDyRqT3E/CSst02ZQ==", + "dev": true + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "enhanced-resolve": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", + "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + } + }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + }, + "dependencies": { + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + } + } + }, + "entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "dev": true + }, + "envinfo": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.7.3.tgz", + "integrity": "sha512-46+j5QxbPWza0PB1i15nZx0xQ4I/EfQxg9J8Had3b408SV63nEtor2e+oiY63amTo9KTuh2a3XLObNwduxYwwA==", + "dev": true + }, + "errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, + "requires": { + "prr": "~1.0.1" + } + }, + "es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "dev": true, + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "es6-templates": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/es6-templates/-/es6-templates-0.2.3.tgz", + "integrity": "sha1-XLmsn7He1usSOTQrgdeSu7QHjuQ=", + "dev": true, + "requires": { + "recast": "~0.11.12", + "through": "~2.3.6" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", + "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.9.1", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^4.0.3", + "eslint-utils": "^1.3.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^5.0.1", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^6.2.2", + "js-yaml": "^3.13.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.11", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^5.5.1", + "strip-ansi": "^4.0.0", + "strip-json-comments": "^2.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0" + }, + "dependencies": { + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + } + } + }, + "eslint-plugin-jest": { + "version": "23.20.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-23.20.0.tgz", + "integrity": "sha512-+6BGQt85OREevBDWCvhqj1yYA4+BFK4XnRZSGJionuEYmcglMZYLNNBBemwzbqUAckURaHdJSBcjHPyrtypZOw==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "^2.5.0" + } + }, + "eslint-plugin-react": { + "version": "7.22.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.22.0.tgz", + "integrity": "sha512-p30tuX3VS+NWv9nQot9xIGAHBXR0+xJVaZriEsHoJrASGCJZDJ8JLNM0YqKqI0AKm6Uxaa1VUHoNEibxRCMQHA==", + "dev": true, + "requires": { + "array-includes": "^3.1.1", + "array.prototype.flatmap": "^1.2.3", + "doctrine": "^2.1.0", + "has": "^1.0.3", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "object.entries": "^1.1.2", + "object.fromentries": "^2.0.2", + "object.values": "^1.1.1", + "prop-types": "^15.7.2", + "resolve": "^1.18.1", + "string.prototype.matchall": "^4.0.2" + }, + "dependencies": { + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + } + } + }, + "eslint-plugin-react-hooks": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-3.0.0.tgz", + "integrity": "sha512-EjxTHxjLKIBWFgDJdhKKzLh5q+vjTFrqNZX36uIxWS4OfyXe5DawqPj3U5qeJ1ngLwatjzQnmR0Lz0J0YH3kxw==", + "dev": true + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + }, + "espree": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", + "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", + "dev": true, + "requires": { + "acorn": "^6.0.7", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", + "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true + }, + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "events": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz", + "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==", + "dev": true + }, + "eventsource": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz", + "integrity": "sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==", + "dev": true, + "requires": { + "original": "^1.0.0" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dev": true, + "requires": { + "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" + }, + "dependencies": { + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + } + } + }, + "ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "dev": true, + "requires": { + "type": "^2.0.0" + }, + "dependencies": { + "type": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz", + "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==", + "dev": true + } + } + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-glob": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", + "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==", + "dev": true, + "requires": { + "@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" + }, + "dependencies": { + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + } + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fastest-levenshtein": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", + "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", + "dev": true + }, + "fastparse": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", + "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==", + "dev": true + }, + "fastq": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.10.0.tgz", + "integrity": "sha512-NL2Qc5L3iQEsyYzweq7qfgy5OtXCmGzGvhElGEd/SoFWEMOEczNh5s5ocaF01HDetxz+p8ecjNPA6cZxxIHmzA==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "faye-websocket": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", + "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, + "file-loader": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-5.1.0.tgz", + "integrity": "sha512-u/VkLGskw3Ue59nyOwUwXI/6nuBCo7KBkniB/l7ICwr/7cPNGsL1WCXUp3GB0qgOOKU1TiP49bv4DZF/LJqprg==", + "dev": true, + "requires": { + "loader-utils": "^1.4.0", + "schema-utils": "^2.5.0" + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "requires": { + "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" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "find-babel-config": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-1.2.0.tgz", + "integrity": "sha512-jB2CHJeqy6a820ssiqwrKMeyC6nNdmrcgkKWJWmpoxpE8RKciYJXCcXRq1h2AzCo5I5BJeN2tkGEO3hLTuePRA==", + "dev": true, + "requires": { + "json5": "^0.5.1", + "path-exists": "^3.0.0" + }, + "dependencies": { + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + } + } + }, + "find-cache-dir": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", + "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + }, + "dependencies": { + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "flatted": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "dev": true + }, + "follow-redirects": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.1.tgz", + "integrity": "sha512-SSG5xmZh1mkPGyKzjZP8zLjltIfpW32Y5QpdNJyjcfGxK3qo3NDDkZOZSFiGn1A6SclQxY9GzEwAHQ3dmYRWpg==" + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "dev": true + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true + }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-intrinsic": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.2.tgz", + "integrity": "sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "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" + } + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "history": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", + "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", + "requires": { + "@babel/runtime": "^7.1.2", + "loose-envify": "^1.2.0", + "resolve-pathname": "^3.0.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0", + "value-equal": "^1.0.1" + } + }, + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "^16.7.0" + } + }, + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "html-entities": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.4.0.tgz", + "integrity": "sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA==", + "dev": true + }, + "html-loader": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-0.5.5.tgz", + "integrity": "sha512-7hIW7YinOYUpo//kSYcPB6dCKoceKLmOwjEMmhIobHuWGDVl0Nwe4l68mdG/Ru0wcUxQjVMEoZpkalZ/SE7zog==", + "dev": true, + "requires": { + "es6-templates": "^0.2.3", + "fastparse": "^1.1.1", + "html-minifier": "^3.5.8", + "loader-utils": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "html-minifier": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz", + "integrity": "sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==", + "dev": true, + "requires": { + "camel-case": "3.0.x", + "clean-css": "4.2.x", + "commander": "2.17.x", + "he": "1.2.x", + "param-case": "2.1.x", + "relateurl": "0.2.x", + "uglify-js": "3.4.x" + } + }, + "html-minifier-terser": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", + "integrity": "sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg==", + "dev": true, + "requires": { + "camel-case": "^4.1.1", + "clean-css": "^4.2.3", + "commander": "^4.1.1", + "he": "^1.2.0", + "param-case": "^3.0.3", + "relateurl": "^0.2.7", + "terser": "^4.6.3" + }, + "dependencies": { + "camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "requires": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true + }, + "param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dev": true, + "requires": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + } + } + }, + "tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", + "dev": true + } + } + }, + "html-webpack-plugin": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-4.5.1.tgz", + "integrity": "sha512-yzK7RQZwv9xB+pcdHNTjcqbaaDZ+5L0zJHXfi89iWIZmb/FtzxhLk0635rmJihcQbs3ZUF27Xp4oWGx6EK56zg==", + "dev": true, + "requires": { + "@types/html-minifier-terser": "^5.0.0", + "@types/tapable": "^1.0.5", + "@types/webpack": "^4.41.8", + "html-minifier-terser": "^5.0.1", + "loader-utils": "^1.2.3", + "lodash": "^4.17.20", + "pretty-error": "^2.1.1", + "tapable": "^1.1.3", + "util.promisify": "1.0.0" + } + }, + "htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "dev": true, + "requires": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", + "dev": true + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", + "dev": true + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } + } + }, + "http-parser-js": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.3.tgz", + "integrity": "sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==", + "dev": true + }, + "http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-proxy-middleware": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz", + "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==", + "dev": true, + "requires": { + "http-proxy": "^1.17.0", + "is-glob": "^4.0.0", + "lodash": "^4.17.11", + "micromatch": "^3.1.10" + } + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "icss-utils": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", + "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", + "dev": true, + "requires": { + "postcss": "^7.0.14" + } + }, + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + }, + "image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", + "dev": true, + "optional": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + } + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", + "dev": true + }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "dev": true, + "requires": { + "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.12", + "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" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "internal-ip": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", + "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==", + "dev": true, + "requires": { + "default-gateway": "^4.2.0", + "ipaddr.js": "^1.9.0" + } + }, + "internal-slot": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.2.tgz", + "integrity": "sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g==", + "dev": true, + "requires": { + "es-abstract": "^1.17.0-next.1", + "has": "^1.0.3", + "side-channel": "^1.0.2" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, + "interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "dev": true + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + }, + "ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", + "dev": true + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true + }, + "is-absolute-url": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", + "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", + "dev": true + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-arguments": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz", + "integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==", + "dev": true, + "requires": { + "call-bind": "^1.0.0" + } + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-callable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", + "dev": true + }, + "is-core-module": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", + "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-negative-zero": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "dev": true + }, + "is-path-in-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", + "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", + "dev": true, + "requires": { + "is-path-inside": "^2.1.0" + } + }, + "is-path-inside": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", + "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", + "dev": true, + "requires": { + "path-is-inside": "^1.0.2" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-what": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.12.0.tgz", + "integrity": "sha512-2ilQz5/f/o9V7WRWJQmpFYNmQFZ9iM+OXRonZKcYgTkCzjb949Vi4h282PD1UfmgHk666rcWonbRJ++KI41VGw==", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json3": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz", + "integrity": "sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==", + "dev": true + }, + "json5": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "jsx-ast-utils": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.0.tgz", + "integrity": "sha512-EIsmt3O3ljsU6sot/J4E1zDRxfBNrhjyf/OKjlydwgEimQuznlM4Wv7U+ueONJMyEn1WRE0K8dhi3dVAXYT24Q==", + "dev": true, + "requires": { + "array-includes": "^3.1.2", + "object.assign": "^4.1.2" + } + }, + "killable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", + "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==", + "dev": true + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "less": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/less/-/less-3.13.1.tgz", + "integrity": "sha512-SwA1aQXGUvp+P5XdZslUOhhLnClSLIjWvJhmd+Vgib5BFIr9lMNlQwmwUNOjXThF/A0x+MCYYPeWEfeWiLRnTw==", + "dev": true, + "requires": { + "copy-anything": "^2.0.1", + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "make-dir": "^2.1.0", + "mime": "^1.4.1", + "native-request": "^1.0.5", + "source-map": "~0.6.0", + "tslib": "^1.10.0" + }, + "dependencies": { + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "optional": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + } + } + }, + "less-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-5.0.0.tgz", + "integrity": "sha512-bquCU89mO/yWLaUq0Clk7qCsKhsF/TZpJUzETRvJa9KSVEL9SO3ovCvdEHISBhrC81OwC8QSVX7E0bzElZj9cg==", + "dev": true, + "requires": { + "clone": "^2.1.1", + "loader-utils": "^1.1.0", + "pify": "^4.0.1" + } + }, + "less-vars-to-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/less-vars-to-js/-/less-vars-to-js-1.3.0.tgz", + "integrity": "sha512-xeiLLn/IMCGtdyCkYQnW8UuzoW2oYMCKg9boZRaGI58fLz5r90bNJDlqGzmVt/1Uqk75/DxIVtQSNCMkE5fRZQ==", + "dev": true, + "requires": { + "strip-json-comments": "^2.0.1" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "loader-runner": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", + "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", + "dev": true + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + } + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "requires": { + "chalk": "^2.0.1" + } + }, + "loglevel": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz", + "integrity": "sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==", + "dev": true + }, + "loglevelnext": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-1.0.5.tgz", + "integrity": "sha512-V/73qkPuJmx4BcBF19xPBr+0ZRVBhc4POxvZTZdMeXpJ4NItXSJ/MSwuFT0kQJlCbXvdlZoQQ/418bS1y9Jh6A==", + "dev": true, + "requires": { + "es6-symbol": "^3.1.1", + "object.assign": "^4.1.0" + } + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "lower-case": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", + "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", + "dev": true + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "mime-db": { + "version": "1.45.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", + "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==", + "dev": true + }, + "mime-types": { + "version": "2.1.28", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz", + "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==", + "dev": true, + "requires": { + "mime-db": "1.45.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "mini-create-react-context": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz", + "integrity": "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==", + "requires": { + "@babel/runtime": "^7.12.1", + "tiny-warning": "^1.0.3" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "minipass": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + } + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", + "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "dev": true, + "requires": { + "dns-packet": "^1.3.1", + "thunky": "^1.0.2" + } + }, + "multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", + "dev": true + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "nan": { + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", + "dev": true, + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "native-request": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/native-request/-/native-request-1.0.8.tgz", + "integrity": "sha512-vU2JojJVelUGp6jRcLwToPoWGxSx23z/0iX+I77J3Ht17rf2INGjrhOoQnjVo60nQd8wVsgzKkPfRXBiVdD2ag==", + "dev": true, + "optional": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "no-case": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", + "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "dev": true, + "requires": { + "lower-case": "^1.1.1" + } + }, + "node-forge": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", + "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==", + "dev": true + }, + "node-releases": { + "version": "1.1.69", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.69.tgz", + "integrity": "sha512-DGIjo79VDEyAnRlfSqYTsy+yoHd2IOjJiKUozD2MV2D85Vso6Bug56mb9tT/fY5Urt0iqk01H7x+llAruDR2zA==", + "dev": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "dev": true, + "requires": { + "boolbase": "~1.0.0" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-inspect": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", + "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==", + "dev": true + }, + "object-is": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.4.tgz", + "integrity": "sha512-1ZvAZ4wlF7IyPVOcE1Omikt7UpaFlOQq0HlSti+ZvDH3UiD2brwGMwDbyV43jao2bKJ+4+WdPJHSd7kgzKYVqg==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + }, + "object.entries": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.3.tgz", + "integrity": "sha512-ym7h7OZebNS96hn5IJeyUmaWhaSM4SVtAPPfNLQEI2MYWCO2egsITb9nab2+i/Pwibx+R0mtn+ltKJXRSeTMGg==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "has": "^1.0.3" + } + }, + "object.fromentries": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.3.tgz", + "integrity": "sha512-IDUSMXs6LOSJBWE++L0lzIbSqHl9KDCfff2x/JSEIDtEUavUnyMYC2ZGay/04Zq4UT8lvd4xNhU4/YHKibAOlw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "has": "^1.0.3" + } + }, + "object.getownpropertydescriptors": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.1.tgz", + "integrity": "sha512-6DtXgZ/lIZ9hqx4GtZETobXLR/ZLaa0aqV0kzbn80Rf8Z2e/XFnhA0I7p07N2wH8bBBltr2xQPi6sbKWAY2Eng==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "object.values": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.2.tgz", + "integrity": "sha512-MYC0jvJopr8EK6dPBiO8Nb9mvjdypOachO5REGk6MXzujbBrAisKo3HmdEI6kZDL6fC31Mwee/5YbtMebixeag==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "has": "^1.0.3" + } + }, + "obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "opn": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", + "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", + "dev": true, + "requires": { + "is-wsl": "^1.1.0" + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "original": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", + "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", + "dev": true, + "requires": { + "url-parse": "^1.4.3" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + }, + "p-retry": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", + "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==", + "dev": true, + "requires": { + "retry": "^0.12.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "param-case": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", + "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", + "dev": true, + "requires": { + "no-case": "^2.2.0" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true + }, + "pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dev": true, + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + }, + "dependencies": { + "lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "requires": { + "tslib": "^2.0.3" + } + }, + "no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "requires": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", + "dev": true + } + } + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "requires": { + "isarray": "0.0.1" + } + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + } + } + }, + "portfinder": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", + "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", + "dev": true, + "requires": { + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.5" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-modules-extract-imports": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", + "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", + "dev": true, + "requires": { + "postcss": "^7.0.5" + } + }, + "postcss-modules-local-by-default": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz", + "integrity": "sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw==", + "dev": true, + "requires": { + "icss-utils": "^4.1.1", + "postcss": "^7.0.32", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-modules-scope": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz", + "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==", + "dev": true, + "requires": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0" + } + }, + "postcss-modules-values": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz", + "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==", + "dev": true, + "requires": { + "icss-utils": "^4.0.0", + "postcss": "^7.0.6" + } + }, + "postcss-selector-parser": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz", + "integrity": "sha512-gjMeXBempyInaBqpp8gODmwZ52WaYsVOsfr4L4lDQ7n3ncD6mEyySiDtgzCT+NYC0mmeOLvtsF8iaEf0YT6dBw==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1", + "util-deprecate": "^1.0.2" + } + }, + "postcss-value-parser": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", + "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "pretty-error": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.2.tgz", + "integrity": "sha512-EY5oDzmsX5wvuynAByrmY0P0hcp+QpnAKbJng2A2MPjVKXCxrDSUkzghVJ4ZGPIv+JC4gX8fPUWscC0RtjsWGw==", + "dev": true, + "requires": { + "lodash": "^4.17.20", + "renderkid": "^2.0.4" + } + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, + "proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "dev": true, + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "dependencies": { + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true + } + } + }, + "raw-loader": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz", + "integrity": "sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "dependencies": { + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "react": { + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz", + "integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2" + } + }, + "react-dom": { + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", + "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.19.1" + } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "react-router": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz", + "integrity": "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==", + "requires": { + "@babel/runtime": "^7.1.2", + "history": "^4.9.0", + "hoist-non-react-statics": "^3.1.0", + "loose-envify": "^1.3.1", + "mini-create-react-context": "^0.4.0", + "path-to-regexp": "^1.7.0", + "prop-types": "^15.6.2", + "react-is": "^16.6.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + } + }, + "react-router-dom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.2.0.tgz", + "integrity": "sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==", + "requires": { + "@babel/runtime": "^7.1.2", + "history": "^4.9.0", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.2", + "react-router": "5.2.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "recast": { + "version": "0.11.23", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.11.23.tgz", + "integrity": "sha1-RR/TAEqx5N+bTktmN2sqIZEkYtM=", + "dev": true, + "requires": { + "ast-types": "0.9.6", + "esprima": "~3.1.0", + "private": "~0.1.5", + "source-map": "~0.5.0" + }, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true + } + } + }, + "rechoir": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.0.tgz", + "integrity": "sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q==", + "dev": true, + "requires": { + "resolve": "^1.9.0" + } + }, + "regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "regenerate-unicode-properties": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", + "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", + "dev": true, + "requires": { + "regenerate": "^1.4.0" + } + }, + "regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" + }, + "regenerator-transform": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", + "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.8.4" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regexp.prototype.flags": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", + "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + }, + "regexpu-core": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz", + "integrity": "sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ==", + "dev": true, + "requires": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.2.0", + "regjsgen": "^0.5.1", + "regjsparser": "^0.6.4", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.2.0" + } + }, + "regjsgen": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", + "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==", + "dev": true + }, + "regjsparser": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.6.tgz", + "integrity": "sha512-jjyuCp+IEMIm3N1H1LLTJW1EISEJV9+5oHdEyrt43Pg9cDSb6rrLZei2cVWpl0xTjmmlpec/lEQGYgM7xfpGCQ==", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, + "relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", + "dev": true + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "renderkid": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.5.tgz", + "integrity": "sha512-ccqoLg+HLOHq1vdfYNm4TBeaCDIi1FLt3wGojTDSvdewUv65oTmI3cnT2E4hRjl1gzKZIPK+KZrXzlUYKnR+vQ==", + "dev": true, + "requires": { + "css-select": "^2.0.2", + "dom-converter": "^0.2", + "htmlparser2": "^3.10.1", + "lodash": "^4.17.20", + "strip-ansi": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "reselect": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.0.0.tgz", + "integrity": "sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA==", + "dev": true + }, + "resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "requires": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + } + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "resolve-pathname": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", + "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true + }, + "run-parallel": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", + "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==", + "dev": true + }, + "rxjs": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "scheduler": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", + "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + } + }, + "select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", + "dev": true + }, + "selfsigned": { + "version": "1.10.8", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.8.tgz", + "integrity": "sha512-2P4PtieJeEwVgTU9QEcwIRDQ/mXJLX8/+I3ur+Pg16nS8oNbrGxEso9NyYWy8NAmXiNl4dlAp5MwoNeCWzON4w==", + "dev": true, + "requires": { + "node-forge": "^0.10.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dev": true, + "requires": { + "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" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + } + } + }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dev": true, + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + }, + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "sockjs": { + "version": "0.3.21", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.21.tgz", + "integrity": "sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw==", + "dev": true, + "requires": { + "faye-websocket": "^0.11.3", + "uuid": "^3.4.0", + "websocket-driver": "^0.7.4" + } + }, + "sockjs-client": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.5.0.tgz", + "integrity": "sha512-8Dt3BDi4FYNrCFGTL/HtwVzkARrENdwOUf1ZoW/9p3M8lZdFT35jVdrHza+qgxuG9H3/shR4cuX/X9umUrjP8Q==", + "dev": true, + "requires": { + "debug": "^3.2.6", + "eventsource": "^1.0.7", + "faye-websocket": "^0.11.3", + "inherits": "^2.0.4", + "json3": "^3.3.3", + "url-parse": "^1.4.7" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "dev": true, + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + } + }, + "spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "string.prototype.matchall": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.3.tgz", + "integrity": "sha512-OBxYDA2ifZQ2e13cP82dWFMaCV9CGF8GzmN4fljBVw5O5wep0lu4gacm1OL6MjROoUnB8VbkWRThqkV2YFLNxw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "has-symbols": "^1.0.1", + "internal-slot": "^1.0.2", + "regexp.prototype.flags": "^1.3.0", + "side-channel": "^1.0.3" + } + }, + "string.prototype.trimend": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz", + "integrity": "sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + } + }, + "string.prototype.trimstart": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz", + "integrity": "sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "style-loader": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.3.0.tgz", + "integrity": "sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^2.7.0" + }, + "dependencies": { + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + } + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true + }, + "tar": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz", + "integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==", + "dev": true, + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "dependencies": { + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + } + } + }, + "terser": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.5.1.tgz", + "integrity": "sha512-6VGWZNVP2KTUcltUQJ25TtNjx/XgdDsBDKGt8nN0MpydU36LmbPPcMBd2kmtZNNGVVDLg44k7GKeHHj+4zPIBQ==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.19" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + } + } + }, + "terser-webpack-plugin": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.1.1.tgz", + "integrity": "sha512-5XNNXZiR8YO6X6KhSGXfY0QrGrCRlSwAEjIIrlRQR4W8nP69TaJUlh3bkuac6zzgspiGPfKEHcY295MMVExl5Q==", + "dev": true, + "requires": { + "jest-worker": "^26.6.2", + "p-limit": "^3.1.0", + "schema-utils": "^3.0.0", + "serialize-javascript": "^5.0.1", + "source-map": "^0.6.1", + "terser": "^5.5.1" + }, + "dependencies": { + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true + }, + "tiny-invariant": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz", + "integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==" + }, + "tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "tsutils": { + "version": "3.19.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.19.1.tgz", + "integrity": "sha512-GEdoBf5XI324lu7ycad7s6laADfnAqCw6wLGI+knxvw9vsIYBaJfYdmeCEG3FMMUiSm3OGgNb+m6utsWf5h9Vw==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typescript": { + "version": "3.9.7", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz", + "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==", + "dev": true + }, + "uglify-js": { + "version": "3.4.10", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz", + "integrity": "sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==", + "dev": true, + "requires": { + "commander": "~2.19.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "unicode-canonical-property-names-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", + "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", + "dev": true + }, + "unicode-match-property-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", + "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", + "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==", + "dev": true + }, + "unicode-property-aliases-ecmascript": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", + "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==", + "dev": true + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true + }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true + }, + "upper-case": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", + "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", + "dev": true + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "url-parse": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", + "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", + "dev": true, + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "use-clipboard-copy": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/use-clipboard-copy/-/use-clipboard-copy-0.1.2.tgz", + "integrity": "sha512-EkauxqyX+us4+Mfif/f61ew89EAOWIArqFpHR0jSG4SwwuDZzDAOeqO7gkK0vi+DQVADeB1RB3xqU3U0oOO3NQ==", + "requires": { + "clipboard-copy": "^3.0.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" + } + }, + "utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", + "dev": true + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + }, + "v8-compile-cache": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", + "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==", + "dev": true + }, + "value-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", + "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true + }, + "watchpack": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.1.0.tgz", + "integrity": "sha512-UjgD1mqjkG99+3lgG36at4wPnUXNvis2v1utwTgQ43C22c4LD71LsYMExdWXh4HZ+RmW+B0t1Vrg2GpXAkTOQw==", + "dev": true, + "requires": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + } + }, + "wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "requires": { + "minimalistic-assert": "^1.0.0" + } + }, + "webpack": { + "version": "5.12.3", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.12.3.tgz", + "integrity": "sha512-7tiQmcTnKhZwbf7X7sEfXe0pgkGjUZjT6JfYkZHvvIb4/ZsXl1rJu5PxsJoN7W3v5sNSP/8TgBoiOdDqVdvK5w==", + "dev": true, + "requires": { + "@types/eslint-scope": "^3.7.0", + "@types/estree": "^0.0.45", + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/wasm-edit": "1.11.0", + "@webassemblyjs/wasm-parser": "1.11.0", + "acorn": "^8.0.4", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.3.1", + "eslint-scope": "^5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.4", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "pkg-dir": "^5.0.0", + "schema-utils": "^3.0.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.1", + "watchpack": "^2.0.0", + "webpack-sources": "^2.1.1" + }, + "dependencies": { + "acorn": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.0.4.tgz", + "integrity": "sha512-XNP0PqF1XD19ZlLKvB7cMmnZswW4C/03pRHgirB30uSJTaS3A3V1/P4sS3HPvFmjoriPCJQs+JDSbm4bL1TxGQ==", + "dev": true + }, + "enhanced-resolve": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.5.0.tgz", + "integrity": "sha512-b4a6BasBCoLzri4MdaeOlDMpls2oioI28CF17csMiav9dq46yvQaKPFNUrCHB6VqQokBDG2VIEEL81jMiQ6Wtw==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "pkg-dir": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", + "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", + "dev": true, + "requires": { + "find-up": "^5.0.0" + } + }, + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "tapable": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.0.tgz", + "integrity": "sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw==", + "dev": true + }, + "webpack-sources": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.2.0.tgz", + "integrity": "sha512-bQsA24JLwcnWGArOKUxYKhX3Mz/nK1Xf6hxullKERyktjNMC4x8koOeaDNTA2fEJ09BdWLbM/iTW0ithREUP0w==", + "dev": true, + "requires": { + "source-list-map": "^2.0.1", + "source-map": "^0.6.1" + } + } + } + }, + "webpack-cli": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.3.1.tgz", + "integrity": "sha512-/F4+9QNZM/qKzzL9/06Am8NXIkGV+/NqQ62Dx7DSqudxxpAgBqYn6V7+zp+0Y7JuWksKUbczRY3wMTd+7Uj6OA==", + "dev": true, + "requires": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/info": "^1.2.1", + "@webpack-cli/serve": "^1.2.1", + "colorette": "^1.2.1", + "commander": "^6.2.0", + "enquirer": "^2.3.6", + "execa": "^5.0.0", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^2.2.0", + "rechoir": "^0.7.0", + "v8-compile-cache": "^2.2.0", + "webpack-merge": "^4.2.2" + }, + "dependencies": { + "commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "execa": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", + "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "get-stream": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz", + "integrity": "sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==", + "dev": true + }, + "import-local": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", + "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", + "dev": true, + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + } + }, + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "dev": true + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "requires": { + "resolve-from": "^5.0.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "webpack-merge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.2.tgz", + "integrity": "sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g==", + "dev": true, + "requires": { + "lodash": "^4.17.15" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "webpack-dev-middleware": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz", + "integrity": "sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ==", + "dev": true, + "requires": { + "memory-fs": "^0.4.1", + "mime": "^2.4.4", + "mkdirp": "^0.5.1", + "range-parser": "^1.2.1", + "webpack-log": "^2.0.0" + }, + "dependencies": { + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "mime": { + "version": "2.4.7", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.7.tgz", + "integrity": "sha512-dhNd1uA2u397uQk3Nv5LM4lm93WYDUXFn3Fu291FJerns4jyTudqhIWe4W04YLy7Uk1tm1Ore04NpjRvQp/NPA==", + "dev": true + }, + "webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "dev": true, + "requires": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + } + } + } + }, + "webpack-dev-server": { + "version": "3.11.1", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.1.tgz", + "integrity": "sha512-u4R3mRzZkbxQVa+MBWi2uVpB5W59H3ekZAJsQlKUTdl7Elcah2EhygTPLmeFXybQkf9i2+L0kn7ik9SnXa6ihQ==", + "dev": true, + "requires": { + "ansi-html": "0.0.7", + "bonjour": "^3.5.0", + "chokidar": "^2.1.8", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", + "debug": "^4.1.1", + "del": "^4.1.1", + "express": "^4.17.1", + "html-entities": "^1.3.1", + "http-proxy-middleware": "0.19.1", + "import-local": "^2.0.0", + "internal-ip": "^4.3.0", + "ip": "^1.1.5", + "is-absolute-url": "^3.0.3", + "killable": "^1.0.1", + "loglevel": "^1.6.8", + "opn": "^5.5.0", + "p-retry": "^3.0.1", + "portfinder": "^1.0.26", + "schema-utils": "^1.0.0", + "selfsigned": "^1.10.8", + "semver": "^6.3.0", + "serve-index": "^1.9.1", + "sockjs": "^0.3.21", + "sockjs-client": "^1.5.0", + "spdy": "^4.0.2", + "strip-ansi": "^3.0.1", + "supports-color": "^6.1.0", + "url": "^0.11.0", + "webpack-dev-middleware": "^3.7.2", + "webpack-log": "^2.0.0", + "ws": "^6.2.1", + "yargs": "^13.3.2" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "dev": true, + "requires": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + } + } + } + }, + "webpack-log": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-1.2.0.tgz", + "integrity": "sha512-U9AnICnu50HXtiqiDxuli5gLB5PGBo7VvcHx36jRZHwK4vzOYLbImqT4lwWwoMHdQWwEKw736fCHEekokTEKHA==", + "dev": true, + "requires": { + "chalk": "^2.1.0", + "log-symbols": "^2.1.0", + "loglevelnext": "^1.0.1", + "uuid": "^3.1.0" + } + }, + "webpack-merge": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.7.3.tgz", + "integrity": "sha512-6/JUQv0ELQ1igjGDzHkXbVDRxkfA57Zw7PfiupdLFJYrgFqY5ZP8xxbpp2lU3EPwYx89ht5Z/aDkD40hFCm5AA==", + "dev": true, + "requires": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + } + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "requires": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "wildcard": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", + "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", + "dev": true + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, + "ws": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", + "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + }, + "y18n": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", + "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + } + } +} diff --git a/applications/samples/frontend/package.json b/applications/samples/frontend/package.json new file mode 100644 index 00000000..4656d811 --- /dev/null +++ b/applications/samples/frontend/package.json @@ -0,0 +1,58 @@ +{ + "name": "samples", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "prebuild": "eslint . --color", + "build": "webpack --config webpack.config.js", + "build-dev": "webpack --config webpack.config.js --env mode=development", + "prestart": "eslint . --color --fix", + "start": "webpack serve --progress --env DOMAIN=http://localhost:5000 --config webpack.config.dev.js", + "start:dev": "webpack serve --progress --env.DOMAIN=https://samples.cloudharness.metacell.us --config webpack.config.dev.js", + "start:minikube": "webpack serve --progress --env DOMAIN=http://samples.cloudharness.local --config webpack.config.dev.js" + }, + "author": "", + "license": "ISC", + "dependencies": { + "axios": "^0.21.1", + "react": "^16.12.0", + "react-dom": "^16.12.0", + "react-router": "^5.0.0", + "react-router-dom": "^5.0.0", + "use-clipboard-copy": "^0.1.2" + }, + "devDependencies": { + "@babel/core": "^7.8.3", + "@babel/plugin-proposal-class-properties": "^7.8.3", + "@babel/preset-env": "^7.8.3", + "@babel/preset-react": "^7.8.3", + "awesome-typescript-loader": "^5.2.1", + "babel-eslint": "^10.1.0", + "babel-loader": "^8.0.6", + "babel-plugin-module-resolver": "^4.0.0", + "babel-preset-minify": "^0.5.1", + "clean-webpack-plugin": "^3.0.0", + "compression-webpack-plugin": "^7.1.2", + "copy-webpack-plugin": "^6.2.1", + "css-loader": "^3.4.2", + "eslint": "5.16.0", + "eslint-plugin-jest": "^23.8.2", + "eslint-plugin-react": "^7.19.0", + "eslint-plugin-react-hooks": "^3.0.0", + "file-loader": "^5.0.2", + "html-loader": "^0.5.5", + "html-webpack-plugin": "^4.5.1", + "less": "^3.10.3", + "less-loader": "^5.0.0", + "less-vars-to-js": "^1.3.0", + "raw-loader": "^4.0.2", + "style-loader": "^1.1.3", + "typescript": "^3.9.3", + "webpack": "^5.0.0", + "webpack-cli": "^4.3.1", + "webpack-dev-server": "^3.11.1", + "webpack-merge": "^5.0.0" + } +} diff --git a/applications/samples/frontend/src/App.tsx b/applications/samples/frontend/src/App.tsx new file mode 100644 index 00000000..931ea6a6 --- /dev/null +++ b/applications/samples/frontend/src/App.tsx @@ -0,0 +1,16 @@ +import React from 'react'; +import './styles/style.less'; + +import RestTest from './components/RestTest'; + + +const Main = () => ( + <> + +

Sample React application is working!

+ +

See api documentation here

+ +); + +export default Main; \ No newline at end of file diff --git a/applications/samples/frontend/src/assets/icon.png b/applications/samples/frontend/src/assets/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..1966e6ddade324846b39edd3aad248e7c61deaef GIT binary patch literal 35505 zcmX`S1yq#p^FI769TJk#7Tq9S3w#s->244Kk?w{?1e8?i2I*E1$t6TU1eTQ$k&;+; z7myW}&i{ko_x*W}$8**@X6C-;nz`qm=as&$1{DP>1pok4nh*ao1OP$|`1d9m3HZzV z8xNJhe^~tQoBJDiIr|4W_&NcqPrM#G-PH7OaB(tpa(EKrGwh@Y00~B#|EU@W|Jqt` zOV1w;;W~I`pSfoEG4Kas_*DjFm|uSWU0z;=v);R1@A_)_CT1<>nuL#=s07~qr^x^q zbQuvr-@N5BAc{*DvS@l0hx2)iLstAJBARGxd)MIX{ZBpRVNwtLn)yz=EW1V7!-URk zW1SwI(Z{6O*qrVzll{}-Mi;YRHh^AGkI7}^Mm+@tl>6!rSxG4oG^Oy89%q%T@?%Bn zWVf*^tn4N8_;Ka^I9)w4s{%W-%eVGVE|Az^ltNuV+y&H{4@j^9{q|suaU- zNX-r2jU2jN03=DTBw9=3ZKT3(G~N#u(9-qYuHS>IuLi zl^*U~XP&ncr5t;ZI^bqh$w7;Zw&b;1I4WIw^r?gLh}$UsZtNZvy%X%>7 zBWLd^Tfdrtx?GK=;IYQxV&6x|U!YFtqS*R_*}8U7b|Evpf&|D8pLcUf^!)jaBG}gN z;nj1qFCAk=10WC%zGqD>zle7I9K;uPV^{|^jq}5);95Za4MD^`$NPC@;-9lRK(U{w z%x*~2*E1l@tj?@Bq*WunR)nTnUaq3<6{NTgn#m%=w$MUJezC{VHw=Kki|}L zK(cXd9~NKWr;{#kxQ@2b4JAdJF@X9>KYAak!-r$u8`4@nD?^a=&JU&}I-HezYOW4G zc-Yw!^<~u%++Qg0vDECI@Smnm)4yE%=?!GPqeH194(+@lqgJdkhGr2MMp7bw`$GC! zPx^1Cw{YCACS^C<{b4z=_}Y>!(ZC?>+V|4o-zmv3y^qdQy-wPvun$Lm&Ik(k{XSIL zMHnrT1M!?19XmrYjIsEI?&dS46z)4X5-60ES~5qgASLof&}gSXQ}dG@_k8PFMQZzw zox8ESQ*w4D$?tPMhq7zOX+glXRe25h(_7ECcAXxMFzQiY0a8w*P=|RrnL@>BK3ir( zdzlJ=K>q#A-5Rc4h0bt`Tj$34`m@U%_Ln}WCarl>3UrLvc1>zJA(4Oa_OOx6y!l{5 zr})B)jk4F&-XlBQ93_DU+!dga$uQ6i`pTkt3t#hJv#1d=Y-QwSKW^Tb0#=zMo|P=B zAwiL*gHm??H?o?(Vt5vXey+3R%pbcKEddPX6!@&a^H!GRX7X9MmT*eL_+x-Hx&K3r}L1M7U6a;X(mH<`&v2yc$)2LrQkLafg==iPPOFN4p!*! zYN{k+&MEzQ=nY)riuPj=K*Tx;9Xfn^X?JWA1LOBjSMR!3F^n8`q(;g`yvk5ka0~0w z#U`e^aYdcub)GVxhL&wED%qy(g@$w6_8;XQz15aQdz19-27ybp>%I)t5wkN(uFG%Q z^5%zl`_}!AaOg5vQSBaOm72Mu^N^kVr62h!od05f*zc3sikrCcm}$~|gzWf83r`hW zJO~$OvFnx|JZk*eK_+*tTvpdGZzY6;vWr}mC7UfBB;22$I;yrt^qd6c(MGP&I-K2X z>?c;WkwxoID7iJAo<5WVm#D}gD!7Pk@h-LUWC>#->FL=C9C|+{!(L$@>8V}d{a4ud8LLl#bs;RG%6y%7je()yn`Tcwb za;9dg1b)Rbge@EABroGwg-mE#g4IZYVUKj#t5zZfnc;fP%?I=`yIQI7eAqs-RynpcPKO+LzyDnKLrnujTS7d=F zNrhI(u@X*V*I|4p?kRu2`v(`7g27Wq*C5>PHBP z{fYLf2irap2*vub-K4QaNL=KblkYV&^U!a)H@`e+dM}|!{Wb@A^%3DpDCy4zI ze4?&lq)ocSf5@%ovr~OWRQP&v2oOu{T$7j5HSO5xxG^}MX(#P^%MlAd4Gvccqv@Yi zVH@n+fvd{$nw{@mB;!^!R;SIVpOwVu>dHgX#`zzw5&2gs6c2q6jZo%fK=A)`rk{$} zQgt;=hpF-Mx`7e3mV~iAzdJpFK2uu@GMy6TI`5anTCQDtYi9K{f+5QGVKjX3+?+3s zTHZ-Bw_v9P8zMxkQ=st+7p1F!E zeVn(HY~6PJe0Q~(mu{D-w>vse@G!^v9i`k;*%}xhlLmZ5%oU3-4m=k{BI<97Q= z8QGT~n@_7{<@le)2WijGYA|Zg=ZSw8f94$qMla8kSXri&^q5b6)bj0*)H-&wMh-y- zqeOd)DQE}}jHi+-GDwS1puKOV(MNEm7UkXJv<%U#wOG-e9lvUXQT3lWK3 zu_E~fnN3Yb$j0|;;)jQK4+VERo*XN9IKEQw$Pa!bee$rctM;~-QKc3cHnXic^>J1k zC0fkS_0c@v9|N&nCvaG<|6Z=smK{~0czj4ZyNU}pd;b#)QK^))^P^RRWp?LhXuoNp zD4Zbah%-1k$2(toIWAT%&9o*Q+}>AN&<0vE_+ht6t9O3ybMSH4Gdhcl6qs%ReezXS z!}IGs!?|;Ho#W5qbH@rvgoDonyHxC+-%hj4LkFdlG<7FcXywC8{47mHfg~861CcLK zb0L{hks^8*ivvYW6D0+!72eb%Y06>eM{+suS|#xvnJJkR87+$RiYR$BJ3D{@Qa*a zM>6aZ7lEma{|3?KQi=6@iVJQBbErsN(j7G8Di49Y+#{irzFE|3w}&c>yljLhSb1_u zib0HG*|Dceq;pVa&ybsBN)acsIh7|~QOn2Y{8z??45k0tDL`<4L#AloD08b%?Q^^6Kry>(VHc;$T6 zN$zVqVs35;MMdEs%C&K5&&z#Xb5OFy=ClpvX}<8L-hVj$Lx~j!2~3NdO>NAI^{e{a zfWq~JOO4fMys-N4rNByul}G07N47At`^C?&oUeHps?)aX{IkbyoZ5T;BA?=m*bduK z7Nba$oVNO;m5iEDMXzi2TjG;1%wk+dquC6L9~SI&8}`2GKQ>urugO~fiM^gRWzsXR zs0C(OOF3d!*mNbep!fc5Dng0%#(W5@XK_)IAb3(QDqihk3M?AR|5jJB) z^}F}h`B+c*%39UIltEZ=Z!SyF~oz@N9 z*4RaSvA8L;av?2tPv?Rq1F*as(Rmr%rE;8E^mcIW-jC2ELi0}zVFniRTKXx>XM2cN zmsHY`Em+{Mgqh)`^WU>>8s{|d?NU2k?SwF`Z^GA9E>6%z`K!TsJpB<)B$jIzvfZ8n z>KFdV5nl^gQcIzQBF^OH2k&obV-vlX*`K;mKg|sw!+d-)@jCO<-0=0UPISu#>`jzt zhc1?UZ|aW*9U28jB#?rGwkjg1?qOX8J-OTqyr*{(D>Bk0_mq)9Ub|3suRl1343@vQ zdcLWuy_+4gcx~t>!?!D3Ji@%A#0c4;^BsAtMa(K@LgnNB5UWH~Z`$h4eK~Yefva$o zuKTu2bes$tLki0EIQ_??>;Cxjt)ACaGJJd*u9KQF8_xLkjYtO!L04c(Pz)%rd6(-m zh(^D3BEh!=mvjG-mLT$N@f2c2T1?!%9n3?`r%iFc11seC$i|~%y-e=BkX<;m@!WE^+=|2|jYwna+&B*=Ld`QL-`aP8Y9{jg(7Re5J5O*<= z?Vtd=?$!Hin@62HtmZROvLfizx4mHO6MRC~4f6eR$K(V^QW%N~N=g zz&M?mXm8X%{pJk$(BLW$3$(ubwEZ%oZFP33o_2ns=TfFel5BNs(fx>IYO8SRynOPG z)7N;NmECLT%vQqQKl`zMu!0PAGR$ZW>JN0bK>`fpe~Iacdtv1Hi) z=KLE*9gZgkfJX&)Z2$hCv05*T292kF2DMnE21uu|RghjCFxV41J(c0u3pWRU1lTj3 zwpoy>^l1rK{ymjAICB7%}|o2BJStUWMfa zY=Qg6v#Zy8leS5X%v))Z!WY7uucle*krVk>{QcZ|r6Mpo@NASVH=01+2s~1Injpo~ zPDTijvaQVhlxw`W)pSV467c@`!I&KI6h?e9>hqMW4s{&gHq+=hn+L z6+WW&?4l#)p>((#Xd~ESckS7>^08`65Dy;MiHRmnI6$92xGG z5EayR>ScR$U}xi@cKT|)QWNlKH>-h=h7|=jB5nI^9QVBwqHwMdfs`4zbAI=@`PlXO z)|t~p?rU~hNX{LS(_m!F+TW5hE%vp>v7Pgr#k_N|Mc%&C^zvD3@ukaUvYNM*-DOY| zZTCLcgM-oNk|7(No@?vS*`u!G?e$ein-OJVer+tnAtt_=h_ICS*-oW9|VYSG~TZ@%N z&dgRx9kCuU)Z4b4XOVxF8~S>1P7qin5k5KCCfBU>3~&rMQTuJoUOPTmaA)h8oicEFH)c_vHeN?gdm&NVNcTU?Q1!z81L2&i@q+B*s z3wvang;>Q-KnU(U~y716V75Otx` z%k#T|2fqA^?Bh&(%6bqReGRBfG~}E{*vBQMPcdLL%H8-gS4B>u@{N0mZOb7$=Mg$A znXB1!LZC~|Zy9SYE53>C-=sPQvEi4e=&X;lYr+Dl-+zE{fpCFLO zXdk=_0>#x?K0`;j>-U{@Gy6};m1QV^_nsx0OBD`(XVy{CFFPT|yIc|}W1#0w2iJ!T z*UBW|4#Uz_p^f7CR*Sj;%hvkns_kIJ!m?b{g(x2pf&BCK*N8Jk(eA_g8gl~e`K*!M z>pX}bOo+527tXb?lc1;&nKjoB~4?I#5V!t7AZ?Jf{Fib zQoqc4CITy_hEkU8pr0i7g{QubjOzN-#l6PBG){NO{h_O1u*F%zo;G{~UCJyJfo9r1 z^Sg8n{!w(!8T-7W<|sIU;*@^de4;sAgMFFkJZ9Q_@|$n*`|H2Awh&&(lHUW}S@JRw^n-*L5a^qU<8$3N=6udweH&K9*#;(%icdZcM5YSVWUhuE2zm@Tq{jhegQ zp8cX1`2};#XF1v+OhrcvqJGc?9UOj zhO#)OTc2ZOuJ%*JeJUnF>bw1~h#q3tvScj&}FLlkNY8-P; zpZ^?)_#oufIFtG6i!U$3*amTDH>C}<+fYn}5r;m!VU!h0bI?}E9s?`vVTR*pCU*}S zw2Vjod&j7HuHmSEX`sq+bHx6lR6P5#YG*1x4uz2pA%VbeWVX(XwT^*CejY;Zh{=3y zD{SKrSzyb(T_z@LNTSLCBh-Zat+QWzb}(H%8KET>#kpn$V@}PA`3Z*`&aHY~>WE4F zeHU~QDtaM1^I{qU`B0^icHZ>Yz`5Jy!KLBLuE7z8(aD5nZJn&lz|@@7AjNKr z(y;F0oqJ~Tm_&z=F!-kz_;5@Wp^!^m(oF1)1H+-SF7Lwll%d0CP9}fz<($XZa*pW` zl6$c?ri`FbK9dGC@*4o2VqJj)FG_}LNBD>cs0SFX?!1*4P37M9J6H)iw;7q+3>;@( zyu1S@B^Q1|RjpqOF26@H6^6`2)zQxXpkF$&Jo?3Dxw3d-e{sQeeH72hB|5|vks;RO z6zGpckMACYQZ00SqqQ4y2vs8950t$~0)3Wj{bT!8-Ov;e=8Rq5xQK%rSpoSFX5Na#)^#0Y~yfh?3~oKOhXR zdq3|erk-LSUAWwETq-!J8|b>TIT~#HGkmGmLwjT-z*iE+uYG6citSpEm|yI zRB0Jwr>rYEKq;RepAz|{e2G-t|6ZJbE8-_XXgFCDY>5kf*IU8(N; z{ok?0JF1oPQtDB`?4qQ@?6l8ve)i36C+7Esio+Zq)2iu{(vG^W zwlPLwDt@4pxwAnAbosJ-@XTXC731k--*=c7Srv@!mIc!;Qx|r`OC^lnFCi%>+HDgA7@oeur0a37DT;EL;vmF{jik_ERFd1#DId)xO8B zv)DiFZ}Yd{t^ucAujlLg4yMA58Dq;&Go00wAJV_m?E_yNToQKLYp$4fQaNwOFT3!* zok_y8GLwOAb&VV}U*G8B%PFT#Jdf%}*{Z0;iJ&T;?8@;I^pN&!vi3(0MXiD~Yvqq_COxU}#!=e=fX9nuJCFX)Cu z5`F0#iPsBv`E@a?;Q1VrfcB9T%1^tMoZNABM-d&;j$FrCEZXws_1~%@Onh6o48NJ3 z);_ilf5ai=$BfJx+&!S+)#7;*{(bR-MtJejc0<_q{%xO|QF}*@?ZkKn zdl7OJgJO4Cd-K@JhEMD1?4Cc82IR7npX@0Dn5zEIG3_aGEy(+giPMAezq4D^H-r19 zht|D~nWy>@JMK|ETpqW>?XB<(-H6P8HG>Tn^?yO(!PPi7nedZow8V!yQiOOfw9I5^{kzfM zYbVP~Pp71Y@uLh$>Y$DwfMNc3mz%C67Y4v z8os8aFf!LEV34tlUOH7Lq5G-S7wUCw1DC9-M7H5QXJ05C6^5fJkVxq@dKx~Z?q~!p z0w-)b`pMExsfxwVMn0(O-_TyfAIADaA{x5-Hr{@YS0y3}pdEFHbBud!n{k@{`?out zOl(#cx)k&Vm$~1NNxcq4&ze%yrD3)^53{^;IR@cw2Yya9gvF-C3R|>BZi&D-4h4 z%NX0d@H4m8*JB$ZQ~IcLvdiZYm@U74IOJA!SB%+I=tsZAAt8pZ?;;oVC$;83lkM-^ z(dF}Qlh4ZcVxI;zMmeLv`*ioF%CRV8BH{5#&uPrxFETyK9(;NWU8w`&P%|2)pvx%5 z;Pj6q*pcJTjO7FN=0Gtp85vmjeowUH7bJY~aAuaL4(xuoZF>MX*iM`ZFW|Ubx6fzN zi85~od>`jm-wDiYKP51Rsx;|>hNK`RFXnJi5*DWxRXY6cpLz0&V=2IlVw2hAWsGd( zkR+*IqTJO=HuKJ2&S&%q~p;G=qeUh?y? zm1jr~)>1OeX;T-R^RpZPJvCo8CrvhhoF9O!o-(!!0G1UN%TJrzc3qPwFsHl1x=L|l zbOHeI%cYoTpc$-jEMO1Bzx3p5le^ zSgW*6M%CxPerT>6{Dc6sb3ks+lzxIg??E-};$C-4b^Mi-yACMF<0~#M8f=vg_<1sa zObWUL@H$>LNSke7R;VGIwc>jM-HX2yl%R0`$&vzJbzCYFBQ0(vWU^McxQRZeKFRiS z+i-XVDiZ0=WY+CDDO;aQ9s1Dj>s5g34gAR&xt)Ktl`lQo+e*C4V=yGlP70h|X`+JA zk03q&5*uY762`qkwXp6D0LKVa-3uYR{bVEUd10@{fgg9!7Y9%lP*Mi8Z*{Z0;j4E6 zc_cM3TXFEnZsrpLYkJH!%JfKWr;yG(Ilzf#Ukeyu;Zxn&rbli%g@kd$rRJZ`-Ejhd zuU7e!9^}{oD+QlrE`Q=Zd5{4}^ZFq`_S~&Xa*PK!SjwH66wrSy+sa0gH;~crD+4jq zg<;SIwdPAbkNsx)N8&J-umknSa}fa6T#Jczb78hG>2c@rZY7i0LBY0!?tcpu7mTgQ z7epU>emBbyEOh%*Yz6Mb_7bdvZN8~&xf*W+fm3I;W_fMCIXtVs!c{syVn43W*~d2z zR@e$&-UGcFqrIt}I?Tv{pZA&J?$h<*%Io(l^rhotBe@a6yNsQ&XUL6$>96( z>(${!si$z%&x{V+xfIkN6g>h0)J$sH?D=iz*QKwDO#daVuZW3UfnS0-yZpb|%3uO+ zDJ58v8e+iz^)D#@*c(v(sq!4cUqTJm(?WiY{8u6=v%LWIrMx{3TGlxvjPVm^$oLXF z9|**P6>G5oWUKKz^Fwk>IpziF3ZwOXyDKO9Gm($%YMZJJT5-Aj4jwVd$lQnv=&isg zIjW2Hj=W_W06qAiQYTYX-9Rka%al;hP z!QtW3L=bz?S}kBbj=>3j*nHWB2@9iwEbJaMc~F6CTuTSbt7SQCzl3zV>5+3_J|X~8 z36Oo~M=54uUK{s6O`-w7KE*usT~>P*CsNo;H17(|!6$cp6gAjuUgYx@x4uCAF?kOm z1Az5}eg43luy&3;-C+A~F*qAJn=2anE#2L0k>Bq3Y9%YTfoR={W>9`Hmb^nEmJ91(mkx7yjRj<|Pj4t}yP@{2w_0_&rP*jk-_l zKQfmn!`^*LssWNiuW{Pfpv&JaN2|G74AoUm+vNfOXBAl?n>`7}meGjvx|s^ckg)bo zakz`l@eB!@ z71AUCepe|gE7|>_kWW%$r&OdwSF5X5( zEJTUM{Z4{` zSJ-c9bYG?@j1+|8bFXYI(5hYc@&-I={_|!~!o(?+S2Ys&d>RoBOngD2KK<8J-crIELx(E4Bn3WgS-_p@~b8c~`dohYc6IWq6}kGDjw z81ns7(0Cf85kB&pKRg&hsPeqTAb`EY3cJ4~;=acE>V2D9-l*-U5s@+%W~AertM$A@ zAb=RNlW7z91mSq4rG$q~1lo=bWB@?>v4~}1Axt@HbJ4{Uq(w1pv!&yi2RlRh+zAsN zruLK=JQxwaUvX(~lf}AiVV$Wxmyxxl{m*bm5R=-IioWgTboYm!5g&*TloN*=k%NI7 zBt$+7VL!WJluYO@`l1~~@UM;&M9&5f*uBW(tOY!(Oyh(rmQvr>6#USL`pc%2X<@*h z>P-!HH+>wO4!W2&cyD3t+GO#nKo5%h^6t~deAvvRf9fNZ%|@paJ34ryE{a?}j4CC< z78#m1l@0P8@KoGjPVfLvRx!5n?d?FqmSe&&9SAM}_KB5G)u73IJ@S#b#oPK?+r$Zp}8 zn*2IF<%fy&C2L;)M}yy*_x~z%M-^WKBiBvmw;xBrd&q$7b<4AI?YXSB!>*`=J76$< zogBZkbM9Iy3x>baX`SDnNcYg8mkdJ>*g(Md-!68!f$UsVxzD0}mV)B~vkD;RgN3!6 zB^>KMN7&(l9C>`j)=hYDrzK|};*i<#OC0>u#iAu#(;6ddSb5WmrsrRje^Nv5&NMXN z@+sz`$?hqxm6bgK1R(SiXJqHt3dO{)y4e-#P>sVbA?Y6gaMQ0~?`y@7H$KSBD$3C# zl4OCchrK_3>B8&*$VSk05-t4~Kb*&;N&PkIGWxHQh$pz^*2@gxTW~Tk&=$WF&!`W+ z<3~>j6f@-N5rk$y7U&KoK%N(xw9x`aC;GiE1^bU2%jiJb5k2FoAIBAOg_2K0JfMLklXNn0KW}Cb9@A%)k zK0y6>0gLpO_8%^~Qtg8~Qx@E`;g_weQ?)$Dcrki>5KL;)>;DB?iZ|SyZF(h}=Wkn< z`@K#_t|ED{HzD`enGxl`qLx_-#Qy7jc-daX;4^ZVscWubp1>PnNQ8>$X>ZT_E~O|> z!(PQ3T)@-PRQ~Ap`yU`mvX6yNy)XXGUF>Fp)T=*oW=7sL-LW-02wTJ}5C6IY@(olt zcYR7KaG&V6%ha!e>3O@Ti9CM(%MqI@|!+!JV*eA%aB(XqB>-_ zt#J4WD>M0t`lRMiqg(m(Q_tOELO@^8Z&`8n?zXgUaMY8L!5d&BIcBZGq_!;p>7!0i z{A8V}_uW%-7G5v_7OIZVIBEe<${Z_za%Z;nqWq&~e)5XM-mcwQ7W~tht?4hLbkfd6 zR=GLOYEYqo%`%ZtJ&vZyT#?W`c??15qRbr#2WWvDdUUl^ZG8$qMf2a;)ma)%pOM_t{$Snr(* z^ck$**ol}jBC%I}p!K>a>vAQg{%dJH8AkN7TxS8_MU??$mnLe#4zGhR!Y=h+%RI2f zjj_7CZB6j`7qIrH9fc7Y_Dp`sN0IW4*Lvpz!8jvOs?v#iJrY|wVeYJf$?XqtC(8WGq(=nI#!1^daE?g|I>{Hpr_Wao@`J1x)! zL6lBGKt_K3@sJ$GLWGYz8yQ*+cyQnR@7e12ql-?VDndzV`JJ=yzQpyP(Es-Qm~tMvS}(g*dy|6e|!c)IQnLD(&oUeb>jK$qd|GcqKJ_b zeMT6++VL~`uX>%AlWJI{5II}s)vy4`*!>$*O4=0cgJ$VB=X~s|k1MDk@Xd(V^&nbF zudR2W*6zYJPF2k~WEJhUQDK*M0uT<+NM?L9!j(j64WXgB5wuaZuT&$dgnE_3OR_5I z2|_WT@7Z;;5FJpg!;e;@#kQepniFC20n-`|^Cn!F8p1Hm)adTBEaeK?*)>%J3uFy9Qs0;o6K`uf(yLupx(kJtQywrr%&it(T=t3Cj2jq8ugfHYD0%O{l=;fGMw;a zLZ~xl`xqY%;;V)X<@$O<=3m3z{#~4PhyQem7AGkqvY8T-vM`*5-Ynj-2e)o6uchAK zVHuw^)MK&oh2j)vHjCDy`u}EU9yY&?$PiY)I8^r!T6U_Sj-W z0Ou5h)B*5L!_?{Yqegr^qL|G7cl#5JDlx8p?Fxy`Z;If7`e{OYKxAsmrneR1v)FT=|^!KH3UysMvZRj zY5xqXfz+of=XGr8r|g+mF+MxiOkOKrD<~)4GYkJ~m&3k3@*iZE;-ARvvkNAAsTm$$ z+$7@y7G%Y|oW&1+mz!7b&?K`_8Pk57R0@QXuXFM~?2?*BiN)D>u2{u&0@l(qe#Ri;H!G5(3I}Bh2<|-#}P_Q!S9zX z)*kVVd;}i_(l;~JBmAdtaaoC<9!)5UE}Rf_-1)IP{arOalgMwu*FMNBf??2RKe|Ew zqv!U#(aSoa`sG{2emCxL!^&fKho789gBDke@XQE|(zDrDy}>mjZOmjY4^dK)@}!%& zj+ETbk-5AN;b7t#1^Z&a232nWYg$@bNZ_>2>5Pm+1_zojNxx zHg;FDRZ-XxS3~AahFt^)j})mC8O3c0l_z!^PI6`D{QaXas*-*9+*3|03|lDiKS-TC zw6Na}N9=w~Fa43p2*ygByHW*_SeE`Gl}zAca4|6rEN5Cr2s)SJw~<+dk%hhT#A-?7 z5h|*l_PE`Rr3a&>6J_rFnR;6ctXZlZ6Y9v4nt$}iSl8|Y|uA4>%d3L7~?(}99UPE>TeOfce{`oYgYXwr#COWoe+a-ELmU9PBc z?buiha!qLe86;pN!fW#3s!8-={-T=$VOH`@!m<7~0b;2QeV_HXtg4r3hDU$ir1s?c zA6l2-)O^8BHMP|1-&-)TJ8}oaquuYJN124nIeB$yBs|en7D$ zUN_gmTBw}0&983CbP;^;nJ{$dx|8*Yox;mfpp**^!-&pX@UgwbU}c zuiO126=QV6B2Fr8(G_a-ec|=wsLgE$fV2>|AJZVeweIu%OsMOYU)|N#;>H95l&D(l z>~63U>*c|BdwzvpgZ0Sj+KcI6Jve(~;ahuU9TD5(lGGsPL? z`^b|kR*dyAizu#5Ild>HC9zfY6}EV`{B_b%3))u_-ozmJ=Zj|sP4DCN7hr?`Ufs#f zq*OOH0ZQ)EJw5pLFF}<(pV+T@xojd^7axDa7R7hQvZ!qN#Ip}`^%u>kVC9;J_BH_m z-!*ag2KgsWC4vHGS{MD|MkHEVFh|o z;0XL4wkY(EKI2!#e_)1+Oeo*n)G<5P0$c4hzNtYt$q{Om_aQcumM{MwpyvFqIbme_MetLB+DPoS+`N_O4YQjZeF zg}Zt(C1BGuFs*&cUZ9!PAkXp;_q`Bo-x&cD-saww+%|4htf`gz|s2j^IO15MJzb5VN6^Yb`$bBS`bc4K%RYEanDo#M+63Uasnb%o@aaXdiiPb})S=^> zIovYT)T~z$RcW$rBFby!%)pPdWHMs;lhSW0P`b*GpJ%t2*`B-r<3hl}q>HVeCQF-+ z7>;sfC`Ooqc%4Tx0qg2! z;7)daMR(@zrdWkMBCjD|KNs81JTxW*m;{pHSLu$v2>1cpgw-p(f{?MlCRxfQv;-%g z2~TQf#I;G{n?Sge@)Tl${u{MRU(8q5DVR0Np{3y_7pYi2Rw@M`u1K7yJYPP^<{5TT^*#xlu#o zKP~xV7W<_T4EgzAWr`JQ_{|Faz6pW}10ghGLQ&z*MWlh5lH1ivKgNqGDML;Y=$>33 z4Rbhi2l)b+s^{{bZr-b&Tv7;~9^_@bE$TPcCjH7$R37t(3YA9XXxMs15xpX=o?_UV z%KtAUH)V&pxjV0!uoZ1ph?+G~V0L5{@DomMWkmIq>sb7~*;gEZy^3q>Lg?iG;Oy5G z*!1g`%0h@!MMxl6+mMuM^oq%rzmgJYCZltuZ}RKdsNa9+J!P3vRNJ2I0&RVCM^ByG zJXB0?DR_w)jA*dg2@@~g#%NggOW0!j$Yv(DwtFW1w@#g#Q8z(;1n@M>|Cdc#WTwCh zi^3$YVdOD6p^wO!SVw32LEAw9rg{)!yqb9<<*&O-YP-FqpCZQRInjkKP+aK3{LP<| z>6POTuJ{&w5M+0mD6j1{FOomss5kRa{K&YqoRL-tL%ai@`+KeuTwsk(*?*dO)AGH6 zwW)2(4)WQFFLxr0GpaeW)kUCtIIc!)5=?7WZGN8iwY~$Owt+#@MzHypGtSpGS>>B$ z44-e6jVj=`K1vMHNP1qAA_dvesI{w-6@cDySn~xxs2FM~Z|Kmt#e}eyUD@pyre+*r zI;y{hYCk3dizBFNN7pfi5=HosQLCcIQ3a^Sl>7hXk0*T*8+)~l@Qr>N{{L({^ulUDAv1Q5CA_FNXr(M!0e26aHxeU0|kBHYizpymUNu~sjz5%yvPt7 zDmEib3S`@Yyr`E}LbTU4%FR4_rWtP*ab(0ls<^TLZM-sa*Q7AK{rVN90nT2u{?lF= zr3g~+rn&xPR9`Yebi6dCp+B2fX4ppz2Y#yH)qw(l<{289jt#Rb(l*TGFlAnISr2jG zguu}OzUp6v()FaJH5YapS_#1Sj&eD(4W=TufAM_mo7-cRs< z;a8jiKLbmNX{I6#n>CaemfT|lH%S^y0j+Lu!91-c`#;%!@sEww{HclB;I(Vn-=K;5 z)_Jq%(7lr|^zXc9LxSxJr`IkvZ}t>Sa{(wdkInu)4UR8vrEkHjP4E+QXiohhU>$hK9J~(ocsLHpMzSi0cMo~Z8$0W947+yQM=Al@Z1yyDw@t#xc?%v`iDF_JIM8>>H ztATYPZYU?m1BxRWnZxfr9PCpBNBnbmXhi7p12ZKLzO0UoND{Gy2V<)+TMoy5^-uE`Qct z!}_13 z-HRWsuN5gqA1Z_Ydw4B0jx%&p&?+D;K?b?UQv@dMcnYw59FzaHV@Ha(M|Ccoj0Z%9MmRYZRUdOY&2y z>{XbhSTZ7GoNlzU3gelVriJzT<|)8BC=)j->*ML^KxV)+M@uF;tl9$tzf+8Mu z&3G{Pu0(U(su1A`+%`)nnTZx8+^%ISyLJfh^}lCA^)fd5f>$Z8FlL661VsE3=b_|r ziDIjY{F3;^y@YmuWS(aT#agx1qKPX2NMx)xp(k2;8%{EtT*|=@{|aZg6-woZ@O#Qg z(94SdOWdeY`Eh2s=HQ%)L)$8?Y)4WkU_g7Fam0di$(re$ab-pzWe8;N+SyD##A4`hIG<1MunzOa0Tnk&= z4}Idg;T61+%nSc<&XXOs0KNbS)e9)4HIxQUbDg|0yJmMT80b4b`l#s*%(j)#i?$Nv z7l8B!r3S9XiOQ?6Q}+bU_zS2-*y@@~un`|FZbxM6+@7Bb zES*b!Etd<5Drz|4;x{pMe)}qwV_)U(hTU$#ACAJ-aroABd(-BBrSLq$F=W;aOzm?_JE+v>1agk$jeu$M{= zyM^5Gm7u}tm%T!nZIr<*8|*#(v-<#mR9*e2MM-9e$RAuS0y<+pGIllC)+g@^>Ol2S2P{;7 zEE=@*Ovz79-P7+syx8c6gQbNtWpt3DB)e5eoEo@Vo`+XFZ}+iOz}Jysy^EufxcKv| z)Q-f??U4V++gray6?I|5gOnhlV9F8hVFx=>=c(7y|Kwxxbcx0mwt$Y)03 z-ifI%4J3n1E<5|RN8x8;r1ogiZiKkt{mI0Z1#QWv=(>y3>deU(qt;!;?Tria=h4k* zZTcpgrG9u{vY*@o|GAK5S7xI?ib=U|S79Ab5!RnEOqIF)+huD_C2ZdT4`^`vjd0i2 zQFV?UYmI#&9aM6&CESi;Z3dWw+LK;-zv*c++>^rA(bl4@wcYO2bDOUqC&6C`IU?J{ zV+?MBbj{>1d${e(I_Y9v z70To?aCC<*J_rS`=n`VBGJ#bkKYc#`q}xo;ze>vW_22{sp8Rq&^1`@#y-KN6U&@Ho zgE*jiw(0t#$C18Y#{F{&KoY$C4s4##>E5QB1O8D&+gvooI-c#dvL4F~t-dlvDyKR< zR|bbk3I25kWCbnp{D8#Uu8COZC<~H))L3@1_kh@NgL~ z)=mW3i{`zL_d&vz`8@_<%4+-gh1dZxp3BsJMRz?tjfl3sC3N52tinC9@YUX=srV^A zEXFoxsPI<;ud(>;O*kcYRH{oSy`@p6wWy!ti%#V4mtK0;3&$fkGfTbpzF-@BW9{!g zG#Jj4%*waKdX!{C0Wp+c4qu#_5c^HB%;i`g=SWZ8>o;bRI&aKYo()o_SS&bHo|e$! z`vlwGX!FnzHFSL+9ChaM81~|0))NxX@tFsAyf(O9;k(XUN!Z1_ge#1r+!ItF^xZG2 z)EyhON=ULHm#Ta4r{RY~qNpEWjnO+2u!Yn&37 zFPhK4-%_4cav1GN7oio%7TZhO9%9kSy7A-U?dm2fRicoj>^>s(3^2N*7niGHsS@Mr z*75|KVfgYIls_dV?k}T=; zzixPq@1iR6@yYPm18eu^IAwR+!&@I%@@AGT+*?sz!xUf*u%_So*H&ItQis29UJ*3U zk1go9vH_`X23OQuNQtS#9_U^DUI}zo(4-o#S5{CpX)Ju!!U;YMDP?=9BK9{$^?Ir| ze?ykz+hym@$AlH{4wAhVpRDY0>huG~(f3k=Pc$~h9<^h<$j1@y@Zx$6uFnpWv-dt` zQg>ana6V0&rQt?|Rgr-z1nxefjlk0gLRBVwbk^1eg9}Sqv1oi*7DXRd1GVxImD@hs zqN66a+q%<*wEhgqK-cqM^=sJkP9kb*s;TkEz_z6-1Drg)*|BM!r5DN=k)X17fbsm& z6&Div3nVnbjH64NCIBT)lu&|M%@Zmcd-W`ahtRWnzU(j)YBayq~@IA2o2%Liyh@=P3FQE_S# zA*}(gB!z9aaEVxP@uXhlF63=LrdVf96>0E z+I~I}a5uDXeA?3tBmC837#be%m>LflWNQM3F5oKzYn;14O2w|W-Lb%qZcs{2&h_#% zKDKUmS@APSK6bi{hm*`~stL$vVX2O|OsL`~Uc7WH@w-SA`qAIRx*#&IyQzV9BJXwB z{myKNFAWEH1(Qt<@>gCP8?Z@Grcd-_wiJm-%n z*jkkGB25I|oR)K{$OO$qH66g-`=2)gNY6hJo5^u}88#NAT9&=5_FWxVUWcQg3DQ-lU}fG34lk%LFUD0J}J4A#u?nM;z|I7oWW&*($af z9$`WurQekQu;nu#@P;Tca|UD5fYVg?Vt5AP+fW^y-s11ObaI+t?9Jo~Z!T!^{1Yf% znZh{gul2(OTApv9Dwt-tvzijC+Hlwr;EWc)0?#J_3BM>6RvN#qs~;Dg`HpCLU*b-`v=wew5b92|)f9?R`HL%Ae83>(5{zGI z--#>kePDS@DCCUI3IB5;6iZ%dArXxk%)Ti#{&zl5XDwAK^gWOg0@utj+X+>`j#JiA zHFmQD+8gxdI0-QV*MwXwGi(1A-R59?-lq!%-u}EN9!mW(Lg=?Rb^CveQG-%s(`C^| ziXR{I%*ia~h7ZT3#~^`IMF={^g|B0vL;vMa-F7~$kOV*ZKp0W|cJ*%uC$^U=*tvfr zrndbd;4#CYX_AC1q5nljlwfp#{=j*dYul+S7MQ$ZCk@$U9y2rnI*nxs(EiLg3Ywu9 zA7jtCZ2*HvNNWPz>@Q0`8*7@yvb3?#UgE0JF*0=@7eL5pxO=FMchJk0g&+W&K-0l8 z;IGHNg{aKQ6t(X@b63Ii&|X{mObG@2dEw}~+tRPU=20pGK>){`0^oYKOXq(# zH+I>H&`!^rsJ`$BsJoM~=#t-;hG#IcmN;NSeMCsh&*Hyiz`J++atM%y(X9=sF|%k% z*Kq%91J{88K6=dp;kzq#=YrXw=VE!eJjVamf=qNcd#k>q9IoGvo5i0Xb1x7e1lA%? zv?w=9MCjH*WwevMSZ)|>W}kBdQRuTY{biC$-Gp#kfqq)7`{VM!F&9cU?#(V+ciupL zT<4z>3`M)ox+`~}ujb+2RTY>oGp)(&S-r8qL`A}L0OsFsAD{ZEMqFjo#i^@!-Ntf_ z-zsymEdB|_kT<}p#IGH%q&r`dd`;5?GC(o*?6{zBL`cA@^_kyLVqIaP__F-;8IBy? ziMDEdXq=mw_nJ%wxYK8!e_j@OM(iISYzm>$z~jp+6_kO_C&f18-Xy>8b=I=;9-ooK zYFtU|+?jeB`oX~Z<+(H)C{9*Qb!8xbJ+J!VC>%GjFT(7l>am|P?AP4sz1AzS%}|~G z-Q)Z~l?5PWTfUVDyn@avwbY{VH-;!93VU{hHsyPj$%OO0^gCYKSLKSER??xj8xe?8 zs)%$Y%w+7HD#KOfIj`p{e^V3h3)sumztzeIS9f5{du^fvV^58=0rQjY|Llb+KYI(i z-N$uZKiQKUJoVy+0RfWGK+l%*)-?GM@9mO2O)ZloS^*Ann&@^90v~O&PlnR0PpoU; zE;R>GKlHsVV;{|{7Z?LN<7rWIVm)@SwKD+SpjGZ5)VMOh3a3~N58n zwr>BhOFqkRlndV<`x|QB5C!<$U{wVEwrfB9CZ%*4ebw~@*feH04yPQ&Yxz|H-TG7h zFll_!mDq=R7Z|S~UI%OzVjq`l77sFpZub~onm;iSrrrAo#gr8>Vyi$O7{Js(>yQ7R z5R!%=9ndQe{3pYeB{j#QRj{{eW18MAUV?PKuPYuLZvp#PBf&P3z5PT0`J!TjjkJdF z*1GnNH?eyoltLBiZ)tqRdq_*p1sm8l(729fqRS<|Mcuk?^Q)ujjx^T1`u#RhSA~8n zAo~I=m$dh1%=2pn>b~R<6Y$p){Lha{XqX-Yahf+ExGBGXC-ANY6%fNL#D9} zT}d7j(Nx7mkdNU2+{&Ef_p)a7+CN)~070<&Xnag0MQr;?+ZiQlY<;H(S9kXKXLWAl z=S4KN@lF?gSfRFDYWoVuVTFehLv8el#4G?%px?|vs44)|@eN%gcXu7GAb>M}D9xNa zCEUC{`4)+M2m${Bj*_>!vbwv?mV{0$TX+`%GxS?leZ)YI?g+pBU57COYH6c;LmY;P z|EVkQ&GF{U{{?&4#R%e+u9@9CUfo9&J&IJnHJ&a4Y>fYQJBIg~qAM-MEkJ7Q3#z1V zoDqzH?dDY(WUZe$r203Z?VKu6*m>SYe1H-_HH6!ib`Fw;d_|?gGEhUag1dKzUc$S_ z5>`0y&%b>-#}A(&YOB@vRb~UqcE6x1O?J$kHT3~nHJ0xF@2B*vBxJ+jz&&h*i(j`p zfPW?~N+4C_mjAj943$i_(#9Mgda-ToUHGoJ!vGZ16?OBuEhPtX3@5gE4?!(Of8TH+fl5T~BA67nhD?Mmb-uenS(58eeL%1#Y8 zr)JT#3lQN3XUy%4t8r144|e}wq+5GLzRa9rvBH*GocJ%%c(D{w4CDfV&Uc{U(KJa* zrmT|x2Iop7GJkcHHdPB`v9OZoBt2G{h@BE|QBK;|1WMuepRh0&NL3HCHP#SqCJ%4r ztIC}lkb<9N-a0_que6l)7yp8Ny=x#oM6!={B|YW%_yLt)YPeF>d|tnGbMOw;yBX-d zQ@b%dYkMC6MbN_%(SqVdU}1k$wgU%8r#~otsmssxtbP^sfp+-l9Wt21!plrv$$xPY zNG;GjbM|=43bt)|?yYLJByBe>v)@f0JHeXi<2(2G4p(FfSMx1w`R}_-XaFa4*4JE} zrzlo{iVTZtMz!-$q# zP#Z}8-nJ!)Yk_Ei?NJd7TDBfb0hky(`SPpsvd>a&qk02(mV@1xFvve12i0r(8Hl*= z0bL29(di%N8}GnK#OA{Bh;L^&AY7DNH(3TGjKY1zrl_rjIO_%@ZCjvAwI&ZsLmm#@ zGX9UL#>eK6Z-L?=3o5G5AqH!TdiRaHA?*voO^$k5`npx;(uoH| zfwyAHM~htM00`R>MfsL}o0Mq}r25#wzv=1Q_xrtA6u>mxW_>==j*l5|+dg*}3PL>` z1^AZS7c~SxJht)vd0PL5pn`?%e?mggbDkp7wzIryyGu{*U$M8SG@uKl0sIfqZ>&D+TbYku`J#ap3 zy@4-WG1Y|F1kts!CGQe~ zOMG$KazglvdgQo2;bfx%#-|FbB9%ci?Qg-p}W$m4^ZUy#QGwkP@I=nl)z*Ue0ubo#ly=d=6gM%Ut&k=N5@D+~lM)<+Zn-W&vjjOVVO>!Mn1+0nax zH}p@YjS-fgn|iJ{)*EoARU&*A;_~D&4P@~>o4+p)tiPL z_H}w8^#+p~aef-IF$`82s^Q-ZWTbs|YssJ%YOz9Y{_V&zd~o6Q36Yq5@%g9Yi{`8T z(sQ0m-auam2MSx^`%BB738|!mqc+0OpLMmsuN(vq74(m;d>txKEFZEm6|h7d-Q$U^ zZ59;~dGF9Ud+BqZ66WG^izgue@JLj4N2z6oDS87Po9ug{-LiVX0!LjRtgsq0B+)ZrlXUElg`(`o_muJ4IP z4Xi$-gjpqGPOp3R8~S%61&qC}j*vVS!_BL2z060{asMgheWi=mm7bAhId}h}nby@* z>aXz2p;W~~0af3+WAF2ukxZN>^PA@R5!w`kuAP?{mXW@yTaW{RmU1txN_sJsi|)r< zgZm1@R|>=K@RXb1Y1Ygbo0BvDUEI}Y7{>>szbrP2xc*@Y2vpJw8_4NDLg&>yOeWAV zK7wUtNNlI2EzdbWfYyf_N%*D2?LM$X3;^y60#%Wr@>#Z>$AGids#~LlYh;>nPTlzH zL)D!U0n+u09uh?ch2c~HbXWe(CvD`TVdM#EPNuG_mI69ujB6}uyHeuoqM>@u7Jd0R zwC(H3^4rtHOVNMt4Vq`#KKlM=pnyJ6%VHwlXO}Nm|MEIk%5avy`RL8jK~h!)O-7C4 z^zM$QO?AbZ;u|_(Mw(@cxI>q+5If zftn*xJvOn;@I>WdUE29S?-G(yYc2dve=tBW#l3P4I%Fe`z6(}P+`VTZfB((C1@Q`+ z0f7w^s8aWhvQ613G`XJ8`<+KQm$<5>e=zuz9p@kus5%@Q^iRJ3Fd$z-s!-*#WZ7!N z+s`GBUdq`IrLcF_*pv53f4(` zM00Om2q%X?#>R;)JGtV)Ojo9sWx0M)&MCR{t(RrfElGHn)r zA46CsBne0U6olQ2AIe!wfVw|o5_P`~4S>gh3>CcosT{{wE^^^+Z!0%22iS;9Su`Oq zhu7xfZ^<3!sQ{%##^plJ6WV}2Rv-aQz@q&y5CaC>wT z2cct$%67MWyRenniQi~=xl6enndPUj*!dl?1W2ewTW|NxX|eH`kRo*MTfMV-J`&%3r-?ZzcY>?4Sn7=nYtTbntoP$&`&YZ|U`l z@y+;!uQ5KI)|cn8MWiTCl&jv!KiC4bY%m!*Ra{`Ln+2a=>o|H-HxWORx%u<*5-~@# z?}_RcU~5jRyLHI}DTv?9F5qU*55gjM+xAcq6Zlx~2qBYZ=HT&-iKr9TzR;apt=v%> zuNYi;nW(&IcY0cSWAUgh5q!7ogVNw}gzcF0!s+Q#@0f~PiFbt|v6qS|ieVCdg>d;y z+?YUG93z>m4`-JRUP(=lC3(_s#ractPDLMDyE=bJi7jJIkJ)YYXYZXmJ8pn6t;cd& z0J${~@4+j>m_~VU$V8HK zszT~0m-2P+u}hz86hBx0*^7D4aVrRvr(-L4Z&NfLRL?AwGCiw*7#c8`QkdV%qdd!>Q!eQ3>DfmMiZOAtU5MKwG_! zy(i%#kh}Z;<&oR*e|9h?b#@@UIDL~W zaGB%wAp=sBz$5(`NC^WEf!M!)p33~wpg#`KBMx}Nfx8{R^S?m~!?!vE{dW+EY4i4f z{~Po_iT@q+KZ*Yx^goIJU;k_iozd4Lxtp!j8wur`a0Dk*nNx}`w{-C461{KD?Z}G| zt}lsLlP8B3k0I;RS9$%#lv8nQYjR`xT6i#m47(eoGw-YqwNGbW_nmt!U7@M35;~sx z!J*LNRH>Zm9nSve2si$Hw@Te*ac@5~x3-qw;sa_{%W3BEn$+!C`?@CNVW+XDRddrs zy>^QBkZJKR_0DGBk{da#gHcP#9NgxN!jpB3Il@hA1!I0Amw`Y>8La$qe{&b6vT;$Q zWB-(c?A|YtmLCEP3DHbnd0tl*%0(XfOxK^9y=_8Z=Q+E6P&t0KKG4ma_+T>KXGgMd z%KZ4yP$I}lNea38dOmUYeBW$Wefw`LLwEO#@tP@5toLipqkY@TIl8L3GJ0;TF=FxS84}C*}Q7#EZ%y39iJ#&noBK zSDgI;u6fSI_)><=Cl%axh+Zw!=;THjq(<*dpVGNOd9K_^y`IZFbZl`aw)YFK_f6~E_ljTxFL_#$@C!~eKol&j36+N$J*F>xsXAHJ+_&6giQoM8Lz$|cTk_iDQi*~rdZj`2enJ*6^^L9l zU#OrLn<`_ONbdz1*@P`5`&F`HV^g}ztJnOG!mx|T#z#K$ng zTL;=3D=SktBIi-mI0^2Tg<&XWvzqN~U&kqTlibqMEx(1+`(^$6-U@yUqi*+ zq4nIRmMz9(i++W)&+dCA4`GV%8`ZHGs?+mJDEekbiZ*JP&_Cc?-eT02Qj?m-ksjCa ztS~2eN%Xt0EA+(u4`jOF$+1SYzC)w^z>1c>9VO(VXLs*;$&24pXF$&Mivv8|>vUMw zDMh$P8*i<~+Y+nh||sh_O#4d$S8=lqfyWE=OMEK@_*Re|TvmCRim}eryG5bVN<~ zMaMTQO4u)>nGhDhHzW?i{l>8~hCd)~kP~i?937o8Ol}6=RT`u5yDy=n^{z+E3K97mpF9<`!POiqkIqjsu zt&UO{uv3MV_Y;o`R@#~hcnQmuj8hBnQuO|mgG6tV68oLCoRvXgB5j3}s7801`@KTQ zLT6|N?OSc0lG1+XUq?_%M?)gp6~PnVz^S+mWt+)INS7u!Y;rN#HqO(AfSc9J)Nm^# z+V`F;@n$pqSJRX*vzcfLb97pPc+180(Sx|vUk-XhlHG#*X7S0Q=s z*ln@+4xW>P$)t)>i#&PU$Itz|-#zE@xs<-m#yj2ZObH9(Xx;M6T^ist0y|QH89n z&yApxDQnhLf{hlf50uB8x*6q;mV^arjVzmfUW@FMx0j1rxtVbKge z8kSLO?v#SkPGz6tSpK|78^1C3YMbPtV0ppeJN&QUv9@a0m{?_&b!M6Ui1u>U$P@EY z`xR^+W&~O@CP9R#qvsRCUSiZgLHK(J%X)F@MPcvF+l%7kNH6e&@6SiiHY={ilLbo~ z%lk%snLMK0ybK+?x8kpNp0!x3nZ4GR>}li+pljDOjW*X>q!NW8J3qE+B18MVd(Csh zBset?XJC8F)44Uw>qOUhk3)6{!q?m=ecmtuFYKU?_`rDI(Mo267< z;m0L*Xyc^+RHyDIR+d!^F9O{-`t&ki^`3wz{KJFTtWTMUo2tp0+OJ+Qn@cwl%y_-8 zno!e%k;i5wN>Oax_0GEAx$0)3Dh5Y#&uJt)FclK1FFBV)M-RU_vwTPl&V3WciAai%B)MA-5ei zjO3kp+6U!4m6wu<`W769^yv-b0ck2MM3n}{;w&*6O-WDFI6wwb$FF7`3lo2Cfl&G@ zLbWl>TTyf~i_ot)#~CZWJk+aFe0vviO7#>6!vVu}?P1)4_P@kAYeI}TEc@TFn4k9X zkmwg>Rd;cP)Sj!Oe0QpDAXL87xAfijI{mVW9}}J!dI*7-GmPWlAqQ|9$!2(u*|4DD!VeE zxNwfwfbSF6bT#F#MUWOgrl$E7r!TqRmiz9G7ipbKo<%n}rnvHJ&tG}f3nPYj#Yh{- zil@A-yWLJ9NrO1ygh{wDr@j&R6YZzt;{875%Ve>W`l{vb_8{sSu3<1rVi?SopEWWi zY~)1abBGantQa{YJs=WoYxSrjbh9q;wK}M$g*-te+~CgnesKB*YewxrhTp-7mx0b+ z|Fm4gp>#o-ZML+KqUY{k?`AiJ=Zk2~Fq=bf$x!riN?h{Xibt4zVzHl&mxO0@+_Lgn zj4d|@!b`a7GOh;u=gea_;)lCnlj##8FWoe6%AOG^vwm>HbVug5A#bZYbUxD&Sx*`f zy4s2vORpPKVwtEoR0A8zVNjDf;pRKr-+#^ehYbwi{7KSV%-n_2U7R*K%kw-A7F1Be z)4b{1HnOKC6`!owpB#ionV^%~?x3mp^eEhb@j08x;<#;Y69W!L7SyFytjaNVrC?!^A z8$Ng+Ld0k>mW$HLnLfBDeJ2uxIkjP4D9Bu$6B(~p4VZgUAjpDz$fqljeOj_Bv`ALIFJfmGgLA)ocELC?mv74HGfx2O zD=Y0O{bXy1f1hn}qJz+jm79V9=;T> zBS{Np+Zj~d9K(UR_D&FTx~RQlwGXGZPPg@{ ziL7@JKVoVnvWvT7GZx#sq;L~6r1&`!*%HY2XP9~|>;3y>LFnpJ+E^UsKmt2#l~KkO zgbnkLs1x@DH6jyH)Dy+!lc6ZI?s!a8fC2uK!uw?138)=q`NR3~Db)`;xB}{b%I0QM z-FoTUK$p@-_h#QjpyK*-gPHftLKsdM!F@umBJ>biHcS%r%6ZO{P%QK5jZIV!`N`YT zSXpY1!m=?gwOrri?JfgZ1;Q2oMQ^vEOA26j@%N_Dgh;@sl#<2A^WQIf6q73Uhe3G{ zI=?*oBrL;2=&~{#i*KD~G(NQ^R%;GgRLG#_DfbD>vm43#Hax--SFG{Ik}M$cO07!p)Q)$>@~ zEh6rBu`jXE(3p^oew*a}nQe&J$XsSKv&^FG$lC~}7SozOcC{oZxAH((P?KkzWa7g| zJ{RVn0?GA^qka(3wrQSBwb8!De%kUeOkSt$hp-KHt05Chb*=d$ha`*o*k=1P^mNGv zwH0*N;A18E#|xHCQv#PY$|Q|>NhvzWd|a%Lz34F9NBd6-W5bZ-3ubw8^_QTRKUKRL z#`vt}@y$RjF=sdzwXy9H!Rqb(b2oYM91J_%KlD&mVR%N>66R_INuh3`wp-RC+utYr z-AiM=>aA735{UbebX`PxDTgBw%Hru1cQw`6>H4f*yY$8Imf#=M#&%dcEBei7Dm_U& z3dzi+nbkKyD4qX!pu6P=?)p5v5m$v~CQfW&e;=b8s)o5OLSO?2ltQE&@zFo~c-D>o4ba&&}6}e4Ca}mGUdQ z6&=aa?mmzKbDWT@yzBB;Y?nClT9*&GkfsN?(h6DwJ?ZOE-tviJhRU!6M>{j1nM_Pp ze>p}}uuRLao_1yE;+r7#+4w_vnN$1S#ft~Vvl&Al+U)jPIbgolKwtQ~1D~Hs6IXY* z+%J4j8@ZmdA{uLPY9Gw#2U7|DLu#ksbj@4M)VN24DatB?41b#qAoX?q;pIZw5O^7%2xSMFp_bl6-TO(d&uXcxkfgoof z%Q(bw+D&GfD`fUnut8}l4068IXjL0Pz8O@S*ZxLM-~)Z)ytq@j0GrKN226Pb6sX$8 zxZCbGCdK#$x5GnxB{jW_8QLtE^vNjqY5>1m=a3URIF@ScK-L~LcCz+Dnmv%}MI1Zo z#HpvS+E{R|MVFnbN!YZxdUR>5tC_zw>VayCHl5b{HdE1-rO3m4mL>ZWRXlB(`l+F* zn86tq?4R~Fj@HyyZNV%F+!ZU+HZY~Ty+h{+(-59D9VyBp;KMq7houV5be0*u{2jza zNNz`-0uLtczlo21uKIiWOy*6#h1%UYO~xX~#>QD}GRw!rb8FnlW3o%h&JuPxA3=qd z9yb$h`)-EssOX&~zYUUqbj%Q}$^^NQpYfXyH6uWWmPZ{A#Xh=8VA>wt_nYX(!y8-F zPLbj9mWz+illjihQY0JwaBg7Ldi?kRV6d>?^q`DTDmSaTDrwhHUjB}5O+=2z`;6$1 zDi(pv5Wl<;;lV+-t$L<2jz*TkKLbU%smGd97rG%ZEAK)`kZ-{)~@vjfDBBy(m!t~r)m4qfC!=BeZwK8g&qwkj^9?8Ew zKnaike)d=(S!z3VbiX1>JZL)>y4)hI%$e#wsWqC@Kfl<= z_P`w7)&9%C_Gi8sNkQC*)PMW(yR6v?R*sFWI-Gw4x^MJ0 z1=rm81db{(%fzMra!2-kVs9grNqi;USoYN~nw8q|BijPwpC{3(Q&RCQ=D}QRERJUp zl2JTn!nT`U8|0^}uiH|-B&Eg9Ujo_)ZBZMs$GT!&C;Q|(oR**O@0onBVUkgd<)MFS z?|Sg5E4}hDcDQbvofEv&g5ZMXpgam*{zeKhXQTa0iTZM5Z7~7aze>lfg8~n$v&!)3 zJ!^kEa`2joPYTEVbqM8O%B#Zwe+!7GP}GQKOEmKeANAy&1A*z^O>C1?m1IUHIJ_~2 z5moU_prH&rU@r|aR8J*;M3U;HX$9@7P9#9H`m2#2L(K=6*_!zn#qLqGJSTVET8zQG zfc?HmW|Op7Z|B^t@F-I)KrPH}D&=9;Y)j<}U2 z6nPA*-)E`Il1OI?P>D>!e$!frJgodZ3)rHnAm2db5DWQfT|-cKo^@UCMf0R~HGyT* zPQr_ci`niIcLO1CrphfZoS-zo?2zy5TZ|*(ZgYeOl44F)JeH_mkZa=(22xFl2yAxo zy3~%k3ym>?i?J*2D|fT#DN7CNJ|F|7`vJ(Ox-oBbCnVK#a}30|F7WD;oXogc$coB( zXAyXl_ruoq4YO|+yp@Hbuwo3=+qhFbQ#TN6`@WM{p+BLE8zv#m8ZJpQ_5$%sd}opM z>W_SWCThot2$6njUi`i0iwbiTwD}LWoj58bOU>@s9lPmKdx1mdf?{ULEun0}{w&276~P>9pGbLZI(VVncB`67Fr zn8cU;4PnkhVzt>~Sv4M+G>Ip5X|?`F(`4nw&of4tw@Z3+Rzc|B^J8QlfB^pO;1%OU z*iPf?=W(@HZ9G+U2eA1Om;LBIyhDe`)IPI>CYsPyP+o%#-OY6PM(3ZFdp^T zkH_P+gE{i9WP<@QhDp~9ii@$Ke%VKy7?b3CdQJ?v2Gy-VXroUkQK%z%m!Fs6DOLgN zhB~IZ&eUlrjb+K*r~Arbt~ZA%UOp6p5oJD2B1M+F$1*|nTq_!3igQ2hYVB)3wt91( zc?o1JIa?8$YY_;w?fr z)Q-4(R!O67YCF!5uatSEzCo@5{;cJ4byoo-zXe?yNFPiB{6wbHqvMb%;jOU2DdD-a z<*w4Gt*y15*~>h;&ypD3$pEIduih@9C z$d&qCr^a~$JmI9&zxG~u$sx;a_DPA6UFW_`o%bgi{!#o@Om@Rsrn|MS=MeR7at%Q|%D7ji zl8fYdEpC3zY_t1V()%`!1HV?SPlDG+|90mw*3VDRXcrQ|n1fC4T^~Fee5fj4maa8Y zA!vOEzGN?E765rgfYs@8zu(Qz`0ZPNpnX8FsZGUZ$KiLbMOO0yZM&f;nG2>(Q%eb@^SfH7KWRoG%3DB4&fIi2Yn zJC2~C6Wo(MK|nF-^;JfenPgdqGTB>EG>YMB|62sp_UqP|{ukY9kBB)t2Z)H})KdjV zu&6-w(?T`DY|mQ!ypm$Lg3lBn5oxjS7gJ((6Vn!>aq4B?jKZCw`TCf*0}cC1IhcM> zZJrNHmWDpAXn>vtK;FJB)t$s2@1~=b7O`<0^m$&$%-p1Ce4}7&Vc_=bnG8ZX7B9KO z62HotNu3OpE@f>z9-xXZ1k%tl77i8Ht9~?h{Ze?MHt};QeMJ%JbAhT3Z0jF)?*?&| zL`=CqC)h3aP2os3Sdk1fVcpzzT7t|)PdEN%+=tc2imJ;A+4{BD zlxoO6tLkqCl@7syK1JUVs_lHfX}4ERaca6*v5DE#`+X64iAJ0tpNxNQ#9VxNb|fWZ zOe`2YmguU!>?RsX((qh{c9aui+lp8_Hb!4A;GvRK^(?ZA!n{im5J;pX{U*!z2Q}g? zUd?`KOuWykMcl}oXi{gTtSo#ZeQ#3O)x>3P#9wRn2n{E?M5c)|IWq7>uvtwZ9}J{e z^qG&8;)%c#+{gY-Zy*zh!Ew}P7>v#3wDeI9)6+UCon<~@>^b2($rZG;{KT~(uM(0f z4j;(L;uo6shb7}Sl&?;X=1_w@U#faz#KNORs+DD;g8KKY?qaie(I<&i)}NBQd}G>^ z=wMR8fBb`L`ok;Qv#!X2xu7J07$#FgcnWLG65k04vNg9Aum76zIGxjVV)b$obWs5| zl>~k-Jjt|3g_eB&zUf){gja}UPJ!b3eieNKsprv~#d@wi1L2eU95K&hmqwRpvmTqZ z$Mx5;AxxVI9b7??9hNWE1y(9Ymwc5<6eHtT{KIl#Tm(pobjM$zD{@m! z__F-JtkQrJaVI5NsE9`8c=f~*Efh7^3{DFDXR1$LSEIdWhW8_VSO2~qdg{0)+X8`c z#bp~tTtzgpO#Q(laFFqpDYvfDKpKOa=x zpf2v8q4Ioh>p@WM5>kflCfn?C+Cz*#Tb`hc8LRhoOYixkV0v`TTX=r0sVIY!ZJ~ zy6X7P;5Xvt=5nSz_Ah3cdX_&HHnNcw*w{*=+58-D^s)nRE3)K~CevLGx!}gC?#PdP zacRRQ=6$)xk^MrwqNIn1ceuQVykCzs=`{J#w1K5r@11(C2I0`k{@fSpvRyGPT{$yw zGMXe6BwG=^E?J6n*`>FI&dsMZo9^Au{1TTnt7XgdPK%C4Xs!nlBe#b-4~%)kSW$p5 zpZoY*kPZ3$4rHi*!6G$~x0U{8jhCO11#>s|$s`YJk+f7sL^q%4{?i41sW6FK+YExe-8(W(!_955n zD~7YxH>MqZ%i{J?CxpG{u2J3!mJ$^JL)?s4hFMx*pwn^DL3}Ct*nkqnb2fOO=Bd%v zPDfSeo(UnTD9AN6oG}W26(gtyVQQr2a#0wvO)cbTrTwQ9Xlq2NJo!3a$`7TG+zPz9 zMA_+UTGRqcZt5Qk4$}e!HxfCQbpR z$YNak`{Sb)p2F5?8$k25dz-9}bq7P3{lf#>orvgIr$X?7@C*h}`r z(=Uz6k##c}lC7%H6OTko zJb6TR%;|u3b0r;KX&gp*PV+bN$kA4#bnPZm2FD2NgjT|-AYNH!ld}X0be(Mez(U{BXmyPR` zE}DOxn1H)ET%@DhjXos+1KBcMWoU%hx$(;+e2;TD|J9ND7ytS>U)eVya@WS2`Gli) z-t`|MvI36^60)e351Onp7J8-Yx*Te{Y*j;joSLlu>|~|XNk*ki2($6C)mLyI{hVve z=>s`bixo~T4HuHI@4mQ_?usPpCpKUY8K5z$5gpAA4zYcLsB-iZ`fvjA(#!D^UW1>x zdO~yc5H_@MJ?hX>ML*RO7R}#kkd2cr8~WBy&>+3p5XFP~nOxbUJQWLJ__K%w9iG{e zG2Qncs>RP|@yuhGv41+s)Ia?zoh>a;9CmM|x>6N$k1{RVR||79(PaC2_Vf6PdyWS# zB>vS!UhUFFSj0q!p75ns@3e_v2STUmKq+en0h?rMAs{ zLLy~x!P%lSgK_2db$_&l)Y=cx^){YeerS84VQaB(U0t&?60J63ItJ1C#E)3mzBpJ;d( z&+>Q7;9S*(*AymiQ#navT1vB#*8d|>yl zr1PO*NvY`fVW3Bt^?}h%lE}3Raxg7xZmnwy)tGkB_+?5(oV~(6W@$a`8+vs{ z3T2z`%Ipk6R<~NwP zD;Qt;`Tmf{eaJA*yCYJ^h~p4XI>X|bze&K?%*^G@w#CTAN2EQChK-Ka;+rY2BkM`t ziMQ#9XQ2F%CvPn-4d@bk5L?cMEcDhlM`rTPk9IwYg%Vt9f%;hPdrVVXw1O9`D~^$L z*3`iqJ~=v48kCmx9rq~oeYD-(oDtA+%Z1KEFI6bDPPwjSTXtu8{p7?GZQ}8o5nE8#SaW>jkE+F!YGifT3p1TcLoP}R zY`;6(ve20%H%(eQOlzb@Pgsg-Hyx#AEJ#c;6X2`W*h-+Pz^ui=)q_RQoiX|8>pebg zT1LBl-AmsYQ=iyodTyUZ;WrDZT^Z2s`yrhVX%WJ`tf5|^0mcjVkM-Q1*p4^Lk`hYZ z^QyPnbXtl2apv_4B1a#b?Y1gUi)*hNep(2p9ipSXwCoOs{a&ncdns>f&(C95{xcL) zq`XJ9qo4b;WYG~J&+x&)mJwpiN{g>fePzh%rP}-{4}SCU{JOHxGy)Vhd-)2GbT^KxFRXgMe zdR;!)qm{1N@uYt0dRX*plFK%Wj+1SLa#_N5S$6xmKn@f~AU#3YAV$~ojp#zvp~2Bl zLw>)_%a=YRVhD@g|1;AJt&IQsUdB%@je6~Ku{x&Qlshnpo$ccJts!X>bt^t@s6X}V z*JHNZtu=m;LGs&g##_vJekV$H>z2z2zfUP%E4E924V>6itCY#=nQqOs_N0ZdQ-Uo9>2uKE7ar#M|=CCw{HUxw&I4uo7rg3140*C*zzgy*Y;A ztJ-z*r;{&E-)(LG?A>dgTMQ3X{ql?6-czmYI{W$9s>QvYCT8bOz1c3FI=%nxBU!_{ z@{#dY+d}*GlM<8b>T2|>1k0a3-k^Ucf7afI&DlK1`?^!l++)!LE-f_`>-^&C16pG| h { + const [result, setResult] = useState(null); + useEffect(() => { + test.ping().then(r => setResult(r)); + }, []); + + + return result &&

Backend answered: { result.data }

+} + +export default RestTest; \ No newline at end of file diff --git a/applications/samples/frontend/src/index.ejs b/applications/samples/frontend/src/index.ejs new file mode 100644 index 00000000..4cd05b48 --- /dev/null +++ b/applications/samples/frontend/src/index.ejs @@ -0,0 +1,10 @@ + + + + + Samples + + +
+ + \ No newline at end of file diff --git a/applications/samples/frontend/src/index.tsx b/applications/samples/frontend/src/index.tsx new file mode 100644 index 00000000..ae31e413 --- /dev/null +++ b/applications/samples/frontend/src/index.tsx @@ -0,0 +1,6 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; + +import App from './App'; + +ReactDOM.render(, document.getElementById('root')); diff --git a/applications/samples/frontend/src/rest/.gitignore b/applications/samples/frontend/src/rest/.gitignore new file mode 100644 index 00000000..149b5765 --- /dev/null +++ b/applications/samples/frontend/src/rest/.gitignore @@ -0,0 +1,4 @@ +wwwroot/*.js +node_modules +typings +dist diff --git a/applications/samples/frontend/src/rest/.npmignore b/applications/samples/frontend/src/rest/.npmignore new file mode 100644 index 00000000..999d88df --- /dev/null +++ b/applications/samples/frontend/src/rest/.npmignore @@ -0,0 +1 @@ +# empty npmignore to ensure all required files (e.g., in the dist folder) are published by npm \ No newline at end of file diff --git a/applications/samples/frontend/src/rest/.openapi-generator-ignore b/applications/samples/frontend/src/rest/.openapi-generator-ignore new file mode 100644 index 00000000..7484ee59 --- /dev/null +++ b/applications/samples/frontend/src/rest/.openapi-generator-ignore @@ -0,0 +1,23 @@ +# OpenAPI Generator Ignore +# Generated by openapi-generator https://github.com/openapitools/openapi-generator + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md diff --git a/applications/samples/frontend/src/rest/api.ts b/applications/samples/frontend/src/rest/api.ts new file mode 100644 index 00000000..d41dd1a4 --- /dev/null +++ b/applications/samples/frontend/src/rest/api.ts @@ -0,0 +1,620 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * CloudHarness Sample API + * CloudHarness Sample api + * + * The version of the OpenAPI document: 0.1.0 + * Contact: cloudharness@metacell.us + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import { Configuration } from './configuration'; +import globalAxios, { AxiosPromise, AxiosInstance } from 'axios'; +// Some imports not used depending on template conditions +// @ts-ignore +import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from './base'; + +/** + * + * @export + * @interface InlineResponse202 + */ +export interface InlineResponse202 { + /** + * + * @type {InlineResponse202Task} + * @memberof InlineResponse202 + */ + task?: InlineResponse202Task; +} +/** + * + * @export + * @interface InlineResponse202Task + */ +export interface InlineResponse202Task { + /** + * the url where to check the operation status + * @type {string} + * @memberof InlineResponse202Task + */ + href?: string; + /** + * + * @type {string} + * @memberof InlineResponse202Task + */ + name?: string; +} +/** + * + * @export + * @interface Valid + */ +export interface Valid { + /** + * + * @type {string} + * @memberof Valid + */ + response?: string; +} + +/** + * AuthApi - axios parameter creator + * @export + */ +export const AuthApiAxiosParamCreator = function (configuration?: Configuration) { + return { + /** + * Check if the token is valid + * @summary Check if the token is valid. Get a token by logging into the base url + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + validToken: async (options: any = {}): Promise => { + const localVarPath = `/valid`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication bearerAuth required + // http bearer authentication required + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + localVarHeaderParameter["Authorization"] = "Bearer " + accessToken; + } + + + + const queryParameters = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + queryParameters.set(key, localVarQueryParameter[key]); + } + for (const key in options.query) { + queryParameters.set(key, options.query[key]); + } + localVarUrlObj.search = (new URLSearchParams(queryParameters)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, + } +}; + +/** + * AuthApi - functional programming interface + * @export + */ +export const AuthApiFp = function(configuration?: Configuration) { + return { + /** + * Check if the token is valid + * @summary Check if the token is valid. Get a token by logging into the base url + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async validToken(options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise>> { + const localVarAxiosArgs = await AuthApiAxiosParamCreator(configuration).validToken(options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs = {...localVarAxiosArgs.options, url: (configuration?.basePath || basePath) + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, + } +}; + +/** + * AuthApi - factory interface + * @export + */ +export const AuthApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { + return { + /** + * Check if the token is valid + * @summary Check if the token is valid. Get a token by logging into the base url + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + validToken(options?: any): AxiosPromise> { + return AuthApiFp(configuration).validToken(options).then((request) => request(axios, basePath)); + }, + }; +}; + +/** + * AuthApi - object-oriented interface + * @export + * @class AuthApi + * @extends {BaseAPI} + */ +export class AuthApi extends BaseAPI { + /** + * Check if the token is valid + * @summary Check if the token is valid. Get a token by logging into the base url + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof AuthApi + */ + public validToken(options?: any) { + return AuthApiFp(this.configuration).validToken(options).then((request) => request(this.axios, this.basePath)); + } +} + + +/** + * TestApi - axios parameter creator + * @export + */ +export const TestApiAxiosParamCreator = function (configuration?: Configuration) { + return { + /** + * + * @summary test sentry is working + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + error: async (options: any = {}): Promise => { + const localVarPath = `/error`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + + + const queryParameters = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + queryParameters.set(key, localVarQueryParameter[key]); + } + for (const key in options.query) { + queryParameters.set(key, options.query[key]); + } + localVarUrlObj.search = (new URLSearchParams(queryParameters)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, + /** + * + * @summary test the application is up + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + ping: async (options: any = {}): Promise => { + const localVarPath = `/ping`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + + + const queryParameters = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + queryParameters.set(key, localVarQueryParameter[key]); + } + for (const key in options.query) { + queryParameters.set(key, options.query[key]); + } + localVarUrlObj.search = (new URLSearchParams(queryParameters)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, + } +}; + +/** + * TestApi - functional programming interface + * @export + */ +export const TestApiFp = function(configuration?: Configuration) { + return { + /** + * + * @summary test sentry is working + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async error(options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await TestApiAxiosParamCreator(configuration).error(options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs = {...localVarAxiosArgs.options, url: (configuration?.basePath || basePath) + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, + /** + * + * @summary test the application is up + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async ping(options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await TestApiAxiosParamCreator(configuration).ping(options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs = {...localVarAxiosArgs.options, url: (configuration?.basePath || basePath) + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, + } +}; + +/** + * TestApi - factory interface + * @export + */ +export const TestApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { + return { + /** + * + * @summary test sentry is working + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + error(options?: any): AxiosPromise { + return TestApiFp(configuration).error(options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary test the application is up + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + ping(options?: any): AxiosPromise { + return TestApiFp(configuration).ping(options).then((request) => request(axios, basePath)); + }, + }; +}; + +/** + * TestApi - object-oriented interface + * @export + * @class TestApi + * @extends {BaseAPI} + */ +export class TestApi extends BaseAPI { + /** + * + * @summary test sentry is working + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof TestApi + */ + public error(options?: any) { + return TestApiFp(this.configuration).error(options).then((request) => request(this.axios, this.basePath)); + } + + /** + * + * @summary test the application is up + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof TestApi + */ + public ping(options?: any) { + return TestApiFp(this.configuration).ping(options).then((request) => request(this.axios, this.basePath)); + } +} + + +/** + * WorkflowsApi - axios parameter creator + * @export + */ +export const WorkflowsApiAxiosParamCreator = function (configuration?: Configuration) { + return { + /** + * + * @summary Send an asynchronous operation + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + submitAsync: async (options: any = {}): Promise => { + const localVarPath = `/operation_async`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + + + const queryParameters = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + queryParameters.set(key, localVarQueryParameter[key]); + } + for (const key in options.query) { + queryParameters.set(key, options.query[key]); + } + localVarUrlObj.search = (new URLSearchParams(queryParameters)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, + /** + * + * @summary Send a synchronous operation + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + submitSync: async (options: any = {}): Promise => { + const localVarPath = `/operation_sync`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + + + const queryParameters = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + queryParameters.set(key, localVarQueryParameter[key]); + } + for (const key in options.query) { + queryParameters.set(key, options.query[key]); + } + localVarUrlObj.search = (new URLSearchParams(queryParameters)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, + /** + * + * @summary Send a synchronous operation and get results using the event queue. Just a sum, but in the cloud + * @param {number} [a] first number to sum + * @param {number} [b] second number to sum + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + submitSyncWithResults: async (a?: number, b?: number, options: any = {}): Promise => { + const localVarPath = `/operation_sync_results`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + if (a !== undefined) { + localVarQueryParameter['a'] = a; + } + + if (b !== undefined) { + localVarQueryParameter['b'] = b; + } + + + + const queryParameters = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + queryParameters.set(key, localVarQueryParameter[key]); + } + for (const key in options.query) { + queryParameters.set(key, options.query[key]); + } + localVarUrlObj.search = (new URLSearchParams(queryParameters)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, + } +}; + +/** + * WorkflowsApi - functional programming interface + * @export + */ +export const WorkflowsApiFp = function(configuration?: Configuration) { + return { + /** + * + * @summary Send an asynchronous operation + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async submitAsync(options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await WorkflowsApiAxiosParamCreator(configuration).submitAsync(options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs = {...localVarAxiosArgs.options, url: (configuration?.basePath || basePath) + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, + /** + * + * @summary Send a synchronous operation + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async submitSync(options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await WorkflowsApiAxiosParamCreator(configuration).submitSync(options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs = {...localVarAxiosArgs.options, url: (configuration?.basePath || basePath) + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, + /** + * + * @summary Send a synchronous operation and get results using the event queue. Just a sum, but in the cloud + * @param {number} [a] first number to sum + * @param {number} [b] second number to sum + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async submitSyncWithResults(a?: number, b?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await WorkflowsApiAxiosParamCreator(configuration).submitSyncWithResults(a, b, options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs = {...localVarAxiosArgs.options, url: (configuration?.basePath || basePath) + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, + } +}; + +/** + * WorkflowsApi - factory interface + * @export + */ +export const WorkflowsApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { + return { + /** + * + * @summary Send an asynchronous operation + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + submitAsync(options?: any): AxiosPromise { + return WorkflowsApiFp(configuration).submitAsync(options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary Send a synchronous operation + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + submitSync(options?: any): AxiosPromise { + return WorkflowsApiFp(configuration).submitSync(options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary Send a synchronous operation and get results using the event queue. Just a sum, but in the cloud + * @param {number} [a] first number to sum + * @param {number} [b] second number to sum + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + submitSyncWithResults(a?: number, b?: number, options?: any): AxiosPromise { + return WorkflowsApiFp(configuration).submitSyncWithResults(a, b, options).then((request) => request(axios, basePath)); + }, + }; +}; + +/** + * WorkflowsApi - object-oriented interface + * @export + * @class WorkflowsApi + * @extends {BaseAPI} + */ +export class WorkflowsApi extends BaseAPI { + /** + * + * @summary Send an asynchronous operation + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof WorkflowsApi + */ + public submitAsync(options?: any) { + return WorkflowsApiFp(this.configuration).submitAsync(options).then((request) => request(this.axios, this.basePath)); + } + + /** + * + * @summary Send a synchronous operation + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof WorkflowsApi + */ + public submitSync(options?: any) { + return WorkflowsApiFp(this.configuration).submitSync(options).then((request) => request(this.axios, this.basePath)); + } + + /** + * + * @summary Send a synchronous operation and get results using the event queue. Just a sum, but in the cloud + * @param {number} [a] first number to sum + * @param {number} [b] second number to sum + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof WorkflowsApi + */ + public submitSyncWithResults(a?: number, b?: number, options?: any) { + return WorkflowsApiFp(this.configuration).submitSyncWithResults(a, b, options).then((request) => request(this.axios, this.basePath)); + } +} + + diff --git a/applications/samples/frontend/src/rest/base.ts b/applications/samples/frontend/src/rest/base.ts new file mode 100644 index 00000000..fe09bd86 --- /dev/null +++ b/applications/samples/frontend/src/rest/base.ts @@ -0,0 +1,71 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * CloudHarness Sample API + * CloudHarness Sample api + * + * The version of the OpenAPI document: 0.1.0 + * Contact: cloudharness@metacell.us + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import { Configuration } from "./configuration"; +// Some imports not used depending on template conditions +// @ts-ignore +import globalAxios, { AxiosPromise, AxiosInstance } from 'axios'; + +export const BASE_PATH = "/api".replace(/\/+$/, ""); + +/** + * + * @export + */ +export const COLLECTION_FORMATS = { + csv: ",", + ssv: " ", + tsv: "\t", + pipes: "|", +}; + +/** + * + * @export + * @interface RequestArgs + */ +export interface RequestArgs { + url: string; + options: any; +} + +/** + * + * @export + * @class BaseAPI + */ +export class BaseAPI { + protected configuration: Configuration | undefined; + + constructor(configuration?: Configuration, protected basePath: string = BASE_PATH, protected axios: AxiosInstance = globalAxios) { + if (configuration) { + this.configuration = configuration; + this.basePath = configuration.basePath || this.basePath; + } + } +}; + +/** + * + * @export + * @class RequiredError + * @extends {Error} + */ +export class RequiredError extends Error { + name: "RequiredError" = "RequiredError"; + constructor(public field: string, msg?: string) { + super(msg); + } +} diff --git a/applications/samples/frontend/src/rest/configuration.ts b/applications/samples/frontend/src/rest/configuration.ts new file mode 100644 index 00000000..15d4df3d --- /dev/null +++ b/applications/samples/frontend/src/rest/configuration.ts @@ -0,0 +1,101 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * CloudHarness Sample API + * CloudHarness Sample api + * + * The version of the OpenAPI document: 0.1.0 + * Contact: cloudharness@metacell.us + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +export interface ConfigurationParameters { + apiKey?: string | Promise | ((name: string) => string) | ((name: string) => Promise); + username?: string; + password?: string; + accessToken?: string | Promise | ((name?: string, scopes?: string[]) => string) | ((name?: string, scopes?: string[]) => Promise); + basePath?: string; + baseOptions?: any; + formDataCtor?: new () => any; +} + +export class Configuration { + /** + * parameter for apiKey security + * @param name security name + * @memberof Configuration + */ + apiKey?: string | Promise | ((name: string) => string) | ((name: string) => Promise); + /** + * parameter for basic security + * + * @type {string} + * @memberof Configuration + */ + username?: string; + /** + * parameter for basic security + * + * @type {string} + * @memberof Configuration + */ + password?: string; + /** + * parameter for oauth2 security + * @param name security name + * @param scopes oauth2 scope + * @memberof Configuration + */ + accessToken?: string | Promise | ((name?: string, scopes?: string[]) => string) | ((name?: string, scopes?: string[]) => Promise); + /** + * override base path + * + * @type {string} + * @memberof Configuration + */ + basePath?: string; + /** + * base options for axios calls + * + * @type {any} + * @memberof Configuration + */ + baseOptions?: any; + /** + * The FormData constructor that will be used to create multipart form data + * requests. You can inject this here so that execution environments that + * do not support the FormData class can still run the generated client. + * + * @type {new () => FormData} + */ + formDataCtor?: new () => any; + + constructor(param: ConfigurationParameters = {}) { + this.apiKey = param.apiKey; + this.username = param.username; + this.password = param.password; + this.accessToken = param.accessToken; + this.basePath = param.basePath; + this.baseOptions = param.baseOptions; + this.formDataCtor = param.formDataCtor; + } + + /** + * Check if the given MIME is a JSON MIME. + * JSON MIME examples: + * application/json + * application/json; charset=UTF8 + * APPLICATION/JSON + * application/vnd.company+json + * @param mime - MIME (Multipurpose Internet Mail Extensions) + * @return True if the given MIME is JSON, false otherwise. + */ + public isJsonMime(mime: string): boolean { + const jsonMime: RegExp = new RegExp('^(application\/json|[^;/ \t]+\/[^;/ \t]+[+]json)[ \t]*(;.*)?$', 'i'); + return mime !== null && (jsonMime.test(mime) || mime.toLowerCase() === 'application/json-patch+json'); + } +} diff --git a/applications/samples/frontend/src/rest/git_push.sh b/applications/samples/frontend/src/rest/git_push.sh new file mode 100644 index 00000000..ced3be2b --- /dev/null +++ b/applications/samples/frontend/src/rest/git_push.sh @@ -0,0 +1,58 @@ +#!/bin/sh +# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/ +# +# Usage example: /bin/sh ./git_push.sh wing328 openapi-pestore-perl "minor update" "gitlab.com" + +git_user_id=$1 +git_repo_id=$2 +release_note=$3 +git_host=$4 + +if [ "$git_host" = "" ]; then + git_host="github.com" + echo "[INFO] No command line input provided. Set \$git_host to $git_host" +fi + +if [ "$git_user_id" = "" ]; then + git_user_id="GIT_USER_ID" + echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id" +fi + +if [ "$git_repo_id" = "" ]; then + git_repo_id="GIT_REPO_ID" + echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id" +fi + +if [ "$release_note" = "" ]; then + release_note="Minor update" + echo "[INFO] No command line input provided. Set \$release_note to $release_note" +fi + +# Initialize the local directory as a Git repository +git init + +# Adds the files in the local repository and stages them for commit. +git add . + +# Commits the tracked changes and prepares them to be pushed to a remote repository. +git commit -m "$release_note" + +# Sets the new remote +git_remote=`git remote` +if [ "$git_remote" = "" ]; then # git remote not defined + + if [ "$GIT_TOKEN" = "" ]; then + echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment." + git remote add origin https://${git_host}/${git_user_id}/${git_repo_id}.git + else + git remote add origin https://${git_user_id}:${GIT_TOKEN}@${git_host}/${git_user_id}/${git_repo_id}.git + fi + +fi + +git pull origin master + +# Pushes (Forces) the changes in the local repository up to the remote repository +echo "Git pushing to https://${git_host}/${git_user_id}/${git_repo_id}.git" +git push origin master 2>&1 | grep -v 'To https' + diff --git a/applications/samples/frontend/src/rest/index.ts b/applications/samples/frontend/src/rest/index.ts new file mode 100644 index 00000000..ecc565f6 --- /dev/null +++ b/applications/samples/frontend/src/rest/index.ts @@ -0,0 +1,18 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * CloudHarness Sample API + * CloudHarness Sample api + * + * The version of the OpenAPI document: 0.1.0 + * Contact: cloudharness@metacell.us + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +export * from "./api"; +export * from "./configuration"; + diff --git a/applications/samples/frontend/src/styles/style.less b/applications/samples/frontend/src/styles/style.less new file mode 100644 index 00000000..b1bece6a --- /dev/null +++ b/applications/samples/frontend/src/styles/style.less @@ -0,0 +1,4 @@ +body { + text-align: center; + background-color: '#eeeeee'; +} \ No newline at end of file diff --git a/applications/samples/frontend/src/utils/history.js b/applications/samples/frontend/src/utils/history.js new file mode 100644 index 00000000..7bef5c97 --- /dev/null +++ b/applications/samples/frontend/src/utils/history.js @@ -0,0 +1,2 @@ +import { createBrowserHistory } from "history"; +export default createBrowserHistory(); \ No newline at end of file diff --git a/applications/samples/frontend/tsconfig.json b/applications/samples/frontend/tsconfig.json new file mode 100755 index 00000000..21ec6c41 --- /dev/null +++ b/applications/samples/frontend/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "outDir": "./dist/", + "sourceMap": true, + "noImplicitAny": false, + "module": "commonjs", + "target": "es2017", + "stripInternal":true, + "skipLibCheck": true, + "alwaysStrict":false, + "forceConsistentCasingInFileNames": true, + "noImplicitReturns": false, + "strict": false, + "noUnusedLocals": false, + "jsx": "react", + "types": [], + "esModuleInterop": true + }, + "exclude": [ + "node_modules" + ] +} \ No newline at end of file diff --git a/applications/samples/frontend/webpack.config.dev.js b/applications/samples/frontend/webpack.config.dev.js new file mode 100644 index 00000000..5a5880c0 --- /dev/null +++ b/applications/samples/frontend/webpack.config.dev.js @@ -0,0 +1,45 @@ +const { merge } = require('webpack-merge'); +const common = require('./webpack.config.js'); + +var path = require('path'); + +const PORT = 9000; + + +module.exports = env => { + + const theDomain = env && env.DOMAIN ? env.DOMAIN : 'localhost:5000'; + + console.log('Dev server address: ', theDomain); + + const proxyTarget = theDomain; + const replaceHost = (uri, appName) => (uri.includes("__APP_NAME__") && uri.replace("__APP_NAME__", appName + '.' + theDomain)) || uri; + if (!env.port) { + env.devPort = PORT; + } + + + const devServer = { + contentBase: path.join(__dirname, 'dist'), + compress: true, + port: Number(env.devPort), + disableHostCheck: true, + historyApiFallback: true, + proxy: { + '/api/': { + target: replaceHost( proxyTarget, 'samples'), + secure: false, + changeOrigin: true, + } + }, + }; + + return merge( + common(env), + { + mode: 'development', + devtool: 'source-map', + devServer, + } + ) +}; diff --git a/applications/samples/frontend/webpack.config.js b/applications/samples/frontend/webpack.config.js new file mode 100644 index 00000000..b2dca762 --- /dev/null +++ b/applications/samples/frontend/webpack.config.js @@ -0,0 +1,110 @@ +const path = require('path'); +const HtmlWebpackPlugin = require('html-webpack-plugin'); +const CompressionPlugin = require('compression-webpack-plugin'); +const { CleanWebpackPlugin } = require('clean-webpack-plugin'); +const CopyWebpackPlugin = require('copy-webpack-plugin'); + +const copyPaths = [ + { from: path.resolve(__dirname, "src/assets"), to: 'assets' }, +]; + +module.exports = function webpacking(envVariables) { + let env = envVariables; + if (!env) { + env = {}; + } + if (!env.mode) { + env.mode = 'production'; + } + + + console.log('####################'); + console.log('####################'); + console.log('BUILD bundle with parameters:'); + console.log( env); + console.log('####################'); + console.log('####################'); + + const { mode } = env; + const devtool = env.mode === 'source-map'; + + + const output = { + path: path.resolve(__dirname, 'dist'), + filename: '[name].[contenthash].js' + }; + + const module = { + rules: [ + { + test: /\.(js|jsx)$/, + exclude: /node_modules/, + loader: 'babel-loader' + }, + { + test: /\.ts|tsx?$/, + loader: "awesome-typescript-loader" + }, + { + test: /\.(css)$/, + use: [ + { + loader: "style-loader", + }, + { + loader: "css-loader", + }], + }, + { + test: /\.less$/, + use: [ + { + loader: "style-loader", + }, + { + loader: "css-loader", + }, + { + loader: "less-loader", + options: { + lessOptions: { + strictMath: true, + }, + }, + }, + ], + }, + { + test: /\.(png|jpg|gif|eot|woff|woff2|svg|ttf)$/, + loader: 'file-loader' + }, + + ] + }; + + const resolve = { + extensions: ['*', '.js', '.json', '.ts', '.tsx', '.jsx'], + symlinks: false + }; + + + + const plugins = [ + new CleanWebpackPlugin(), + new CopyWebpackPlugin({ patterns: copyPaths }), + new CompressionPlugin(), + new HtmlWebpackPlugin({ + template: 'src/index.ejs', + favicon: path.join(__dirname, 'src/assets/icon.png') + }) + ]; + + return { + mode, + devtool, + output, + module, + resolve, + plugins + }; +}; diff --git a/applications/samples/server/Dockerfile b/applications/samples/server/Dockerfile deleted file mode 100644 index d74b98f7..00000000 --- a/applications/samples/server/Dockerfile +++ /dev/null @@ -1,18 +0,0 @@ -ARG REGISTRY -ARG TAG=latest -FROM ${REGISTRY}cloudharness-base:${TAG} - -RUN mkdir -p /usr/src/app -WORKDIR /usr/src/app - -COPY requirements.txt /usr/src/app/ - -RUN pip3 install --no-cache-dir -r requirements.txt - -COPY . /usr/src/app - -EXPOSE 8080 - -ENTRYPOINT ["python3"] - -CMD ["-m", "api_samples"] \ No newline at end of file diff --git a/applications/samples/server/api_samples/__main__.py b/applications/samples/server/api_samples/__main__.py deleted file mode 100644 index 9df35748..00000000 --- a/applications/samples/server/api_samples/__main__.py +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env python3 - -import connexion - -from api_samples import encoder - - -def main(): - app = connexion.App(__name__, specification_dir='./openapi/') - app.app.json_encoder = encoder.JSONEncoder - app.add_api('openapi.yaml', - arguments={'title': 'CloudHarness Sample API'}, - pythonic_params=True) - app.run(port=8080) - - -if __name__ == '__main__': - main() diff --git a/applications/samples/server/api_samples/controllers/workflows_controller.py b/applications/samples/server/api_samples/controllers/workflows_controller.py deleted file mode 100644 index cf4fea81..00000000 --- a/applications/samples/server/api_samples/controllers/workflows_controller.py +++ /dev/null @@ -1,83 +0,0 @@ -import connexion -import six - -from api_samples.models.inline_response202 import InlineResponse202 # noqa: E501 -from api_samples import util -from api_samples.models import InlineResponse202 -from api_samples.models.inline_response202_task import InlineResponse202Task -from flask.json import jsonify - -from cloudharness import log - -try: - from cloudharness.workflows import operations, tasks -except Exception as e: - log.error("Cannot start workflows module. Probably this is related some problem with the kubectl configuration", e) - - -def submit_async(): # noqa: E501 - """Send an asyncronous operation - - # noqa: E501 - - - :rtype: InlineResponse202 - """ - shared_directory = '/mnt/shared' - task_write = tasks.CustomTask('download-file', 'workflows-extract-download', url='https://raw.githubusercontent.com/openworm/org.geppetto/master/README.md') - task_print = tasks.CustomTask('print-file', 'workflows-print-file', file_path=shared_directory + '/README.md') - op = operations.PipelineOperation('test-custom-connected-op-', (task_write, task_print), shared_directory=shared_directory) - - submitted = op.execute() - if not op.is_error(): - return InlineResponse202(task= InlineResponse202Task(href=op.get_operation_update_url(), name=submitted.name)), 202 - else: - return 'Error submitting operation', 500 - - -def submit_sync(): # noqa: E501 - """Send a syncronous operation - - # noqa: E501 - - - :rtype: str - """ - task = tasks.CustomTask('download-file', 'workflows-extract-download', url='https://www.metacell.us') - - op = operations.DistributedSyncOperation('test-sync-op-', task) - workflow = op.execute() - return workflow.raw - - -def submit_sync_with_results(a=1, b=2): # noqa: E501 - """Send a synchronous operation and get results using the event queue. Just a sum, but in the cloud - - # noqa: E501 - - :param a: first number to sum - :type a: float - :param b: second number to sum - :type b: float - - :rtype: str - """ - task = tasks.CustomTask('test-sum', 'samples-sum', a=a, b=b) - try: - op = operations.DistributedSyncOperationWithResults('test-sync-op-results-', task) - result = op.execute() - return result - except Exception as e: - return jsonify(str(e)), 200 - - - -def error(): # noqa: E501 - """test sentry is working - - # noqa: E501 - - - :rtype: str - """ - return "a"[2] diff --git a/applications/samples/server/api_samples/encoder.py b/applications/samples/server/api_samples/encoder.py deleted file mode 100644 index 7a200e51..00000000 --- a/applications/samples/server/api_samples/encoder.py +++ /dev/null @@ -1,20 +0,0 @@ -from connexion.apps.flask_app import FlaskJSONEncoder -import six - -from api_samples.models.base_model_ import Model - - -class JSONEncoder(FlaskJSONEncoder): - include_nulls = False - - def default(self, o): - if isinstance(o, Model): - dikt = {} - for attr, _ in six.iteritems(o.openapi_types): - value = getattr(o, attr) - if value is None and not self.include_nulls: - continue - attr = o.attribute_map[attr] - dikt[attr] = value - return dikt - return FlaskJSONEncoder.default(self, o) diff --git a/applications/samples/server/api_samples/models/__init__.py b/applications/samples/server/api_samples/models/__init__.py deleted file mode 100644 index 260fdebe..00000000 --- a/applications/samples/server/api_samples/models/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -# coding: utf-8 - -# flake8: noqa -from __future__ import absolute_import -# import models into model package -from api_samples.models.inline_response202 import InlineResponse202 -from api_samples.models.inline_response202_task import InlineResponse202Task -from api_samples.models.valid import Valid diff --git a/applications/samples/server/api_samples/test/test_default_controller.py b/applications/samples/server/api_samples/test/test_default_controller.py deleted file mode 100644 index 47e7f3a6..00000000 --- a/applications/samples/server/api_samples/test/test_default_controller.py +++ /dev/null @@ -1,40 +0,0 @@ -# coding: utf-8 - -from __future__ import absolute_import - -from flask import json -from six import BytesIO - -from api_samples.models.valid import Valid # noqa: E501 -from api_samples.test import BaseTestCase - - -class TestDefaultController(BaseTestCase): - """DefaultController integration test stubs""" - - def test_operation_sync_post(self): - """Test case for operation_sync_post - - Send a syncronous operation - """ - response = self.client.open( - '0.1.0/operation-sync', - method='POST') - self.assert200(response, - 'Response body is : ' + response.data.decode('utf-8')) - - def test_valid_token(self): - """Test case for valid_token - - Check if the token is valid - """ - response = self.client.open( - '0.1.0/valid', - method='GET') - self.assert200(response, - 'Response body is : ' + response.data.decode('utf-8')) - - -if __name__ == '__main__': - import unittest - unittest.main() diff --git a/applications/samples/server/api_samples/test/test_workflows_controller.py b/applications/samples/server/api_samples/test/test_workflows_controller.py deleted file mode 100644 index 4bb1998e..00000000 --- a/applications/samples/server/api_samples/test/test_workflows_controller.py +++ /dev/null @@ -1,40 +0,0 @@ -# coding: utf-8 - -from __future__ import absolute_import - -from flask import json -from six import BytesIO - -from api_samples.models.inline_response202 import InlineResponse202 # noqa: E501 -from api_samples.test import BaseTestCase - - -class TestWorkflowsController(BaseTestCase): - """WorkflowsController integration test stubs""" - - def test_operation_submit_async(self): - """Test case for operation_submit_async - - Send an asyncronous operation - """ - response = self.client.open( - '/0.1.0/operation_async', - method='POST') - self.assert200(response, - 'Response body is : ' + response.data.decode('utf-8')) - - def test_operation_submit_sync(self): - """Test case for operation_submit_sync - - Send a syncronous operation - """ - response = self.client.open( - '/0.1.0/operation_sync', - method='POST') - self.assert200(response, - 'Response body is : ' + response.data.decode('utf-8')) - - -if __name__ == '__main__': - import unittest - unittest.main() diff --git a/applications/samples/server/requirements.txt b/applications/samples/server/requirements.txt deleted file mode 100644 index 2639eedf..00000000 --- a/applications/samples/server/requirements.txt +++ /dev/null @@ -1,7 +0,0 @@ -connexion >= 2.6.0; python_version>="3.6" -connexion >= 2.3.0; python_version=="3.5" -connexion >= 2.3.0; python_version=="3.4" -connexion == 2.4.0; python_version<="2.7" -swagger-ui-bundle >= 0.0.2 -python_dateutil >= 2.6.0 -setuptools >= 21.0.0 diff --git a/applications/samples/server/www/index.html b/applications/samples/server/www/index.html deleted file mode 100644 index 75b5ddb0..00000000 --- a/applications/samples/server/www/index.html +++ /dev/null @@ -1 +0,0 @@ -Index of cloudharness sample application \ No newline at end of file diff --git a/applications/sentry/Dockerfile b/applications/sentry/Dockerfile index 9b190cf5..2607f517 100644 --- a/applications/sentry/Dockerfile +++ b/applications/sentry/Dockerfile @@ -5,14 +5,19 @@ RUN chmod +x ./sentryrunner.sh ENV SENTRY_REDIS_HOST=sentry-redis-host ENV SENTRY_REDIS_PORT=6379 -ENV SENTRY_POSTGRES_HOST=sentry-postgres-host + +ENV SENTRY_POSTGRES_HOST=sentry-db ENV SENTRY_POSTGRES_PORT=5432 ENV SENTRY_DB_NAME=sentry ENV SENTRY_DB_USER=sentry ENV SENTRY_DB_PASSWORD=secret -ENV SENTRY_EMAIL_HOST=sentry-postfix-host + +ENV SENTRY_EMAIL_HOST=in-v3.mailjet.com +ENV SENTRY_EMAIL_PORT=587 +ENV SENTRY_EMAIL_USE_TLS=True +ENV SENTRY_EMAIL_FROM=sentry + ENV SENTRY_ADMIN_USER=sentry ENV SENTRY_ADMIN_PASSWORD=secret -ENV SENTRY_EMAIL_FROM=sentry ENTRYPOINT ["./sentryrunner.sh"] diff --git a/applications/sentry/deploy/templates/postfix.yaml b/applications/sentry/deploy/templates/postfix.yaml deleted file mode 100644 index 82107bb5..00000000 --- a/applications/sentry/deploy/templates/postfix.yaml +++ /dev/null @@ -1,61 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.apps.sentry.postfix.name }} - labels: - app: {{ .Values.apps.sentry.postfix.name }} -{{ include "deploy_utils.labels" $ | indent 4 }} -spec: - type: ClusterIP - ports: - - port: {{ .Values.apps.sentry.postfix.port }} - selector: - app: {{ .Values.apps.sentry.postfix.name }} ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ .Values.apps.sentry.postfix.name | quote }} - labels: - app: {{ .Values.apps.sentry.postfix.name | quote }} -{{ include "deploy_utils.labels" $ | indent 4 }} -spec: - replicas: 1 - selector: - matchLabels: - app: {{ .Values.apps.sentry.postfix.name | quote }} -{{ include "deploy_utils.labels" $ | indent 6 }} - template: - metadata: - {{- if .Values.apps.sentry.postfix.harvest }} - annotations: - co.elastic.logs/enabled: "true" - metricbeat: "true" - {{- end }} - labels: - app: {{ .Values.apps.sentry.postfix.name | quote }} -{{ include "deploy_utils.labels" $ | indent 8 }} - spec: - {{ if .Values.codefresh }} - imagePullSecrets: - - name: {{ .Values.codefresh.secret }} - {{- end }} - containers: - - name: {{ .Values.apps.sentry.postfix.name | default "sentry-postfix" | quote }} - image: {{ .Values.apps.sentry.postfix.image }} - imagePullPolicy: {{ include "deploy_utils.pullpolicy" .root }} - env: - - name: MTP_HOST - value: {{ printf "mail.%s" .Values.domain }} - {{- include "deploy_utils.env" .root | nindent 8 }} - {{- include "deploy_utils.privenv" .root | nindent 8 }} - ports: - - containerPort: {{ .Values.apps.sentry.postfix.port | default 25 }} - resources: - requests: - memory: "128Mi" - cpu: "100m" - limits: - memory: "512Mi" - cpu: "500m" ---- diff --git a/applications/sentry/deploy/templates/postgres.yaml b/applications/sentry/deploy/templates/postgres.yaml deleted file mode 100644 index 1d28f13d..00000000 --- a/applications/sentry/deploy/templates/postgres.yaml +++ /dev/null @@ -1,77 +0,0 @@ -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: sentry-db - labels: - app: {{ .Values.apps.sentry.postgres.name }} -{{ include "deploy_utils.labels" $ | indent 4 }} -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 2Gi ---- -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.apps.sentry.postgres.name }} - labels: - app: {{ .Values.apps.sentry.postgres.name }} -{{ include "deploy_utils.labels" $ | indent 4 }} -spec: - type: ClusterIP - ports: - - port: 5432 - selector: - app: {{ .Values.apps.sentry.postgres.name }} ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ .Values.apps.sentry.postgres.name }} - labels: - app: {{ .Values.apps.sentry.postgres.name }} -{{ include "deploy_utils.labels" $ | indent 4 }} -spec: - replicas: 1 - selector: - matchLabels: - app: {{ .Values.apps.sentry.postgres.name | quote }} -{{ include "deploy_utils.labels" $ | indent 6 }} - template: - metadata: - labels: - app: {{ .Values.apps.sentry.postgres.name }} -{{ include "deploy_utils.labels" $ | indent 8 }} - spec: - containers: - - name: {{ .Values.apps.sentry.postgres.name | default "sentry-postgress" | quote }} - image: {{ .Values.apps.sentry.postgres.image | quote }} - imagePullPolicy: "IfNotPresent" - env: - - name: POSTGRES_DB - value: {{ .Values.apps.sentry.postgres.initialdb | quote }} - - name: POSTGRES_USER - value: {{ .Values.apps.sentry.postgres.user | quote }} - - name: POSTGRES_PASSWORD - value: {{ .Values.apps.sentry.postgres.password | quote }} - - name: PGDATA - value: {{ .Values.apps.sentry.postgres.pgdata }} - ports: - - containerPort: {{ .Values.apps.sentry.postgres.port }} - resources: - requests: - memory: "128Mi" - cpu: "200m" - limits: - memory: "256Mi" - cpu: "500m" - volumeMounts: - - name: sentry-db - mountPath: {{ .Values.apps.sentry.postgres.datavolume }} - volumes: - - name: sentry-db - persistentVolumeClaim: - claimName: sentry-db ---- \ No newline at end of file diff --git a/applications/sentry/deploy/templates/redis.yaml b/applications/sentry/deploy/templates/redis.yaml index dac79e80..529a3d16 100644 --- a/applications/sentry/deploy/templates/redis.yaml +++ b/applications/sentry/deploy/templates/redis.yaml @@ -27,7 +27,7 @@ spec: {{ include "deploy_utils.labels" $ | indent 6 }} template: metadata: - {{- if .Values.apps.sentry.postfix.harvest }} + {{- if .Values.apps.sentry.redis.harvest }} annotations: co.elastic.logs/enabled: "true" metricbeat: "true" @@ -45,8 +45,8 @@ spec: resources: requests: memory: "64Mi" - cpu: "100m" + cpu: "25m" limits: memory: "128Mi" - cpu: "200m" + cpu: "100m" --- \ No newline at end of file diff --git a/applications/sentry/deploy/templates/secret.yaml b/applications/sentry/deploy/templates/secret.yaml new file mode 100644 index 00000000..500e171b --- /dev/null +++ b/applications/sentry/deploy/templates/secret.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Secret +metadata: + name: ch-sentry +type: generic +data: + # Mail credentials need to be set manually by the sys admin + server-email: Q0hBTkdFTUU= + email-password: Q0hBTkdFTUU= + email-user: Q0hBTkdFTUU= \ No newline at end of file diff --git a/applications/sentry/deploy/values.yaml b/applications/sentry/deploy/values.yaml index db917580..0fbafa4b 100644 --- a/applications/sentry/deploy/values.yaml +++ b/applications/sentry/deploy/values.yaml @@ -16,24 +16,26 @@ harness: limits: memory: 2048Mi cpu: 2000m - -postgres: - name: sentry-postgres-host - port: 5432 - image: postgres:latest - initialdb: sentry - user: sentry - password: secret - datavolume: /opt/data/ - pgdata: /opt/data/pgdata + database: + auto: true + type: postgres + size: 2Gi + user: sentry + pass: secret + postgres: + initialdb: sentry + env: + - name: SENTRY_SERVER_EMAIL + value: zoran@metacell.us + secrets: + - name: ch-sentry + key: server-email + - name: ch-sentry + key: email-user + - name: ch-sentry + key: email-password redis: name: sentry-redis-host image: redis:latest - port: 6379 - -postfix: - name: sentry-postfix-host - image: eeacms/postfix:latest - port: 25 - hostname: mail.opensourcebrain.org + port: 6379 \ No newline at end of file diff --git a/applications/sentry/sentryrunner.sh b/applications/sentry/sentryrunner.sh index 37921f09..0e7c947b 100644 --- a/applications/sentry/sentryrunner.sh +++ b/applications/sentry/sentryrunner.sh @@ -2,7 +2,14 @@ echo "**** S:INI ****" export SENTRY_SECRET_KEY=$(sentry config generate-secret-key) -export SENTRY_SERVER_EMAIL=${SENTRY_EMAIL_FROM}@${DOMAIN} + +export SENTRY_SERVER_EMAIL=`echo ''|awk '{print ENVIRON["ch-sentry-server-email"]}'` +if [ -z "${SENTRY_SERVER_EMAIL}" ]; then + export SENTRY_SERVER_EMAIL=${SENTRY_EMAIL_FROM}@${DOMAIN} +fi + +export SENTRY_EMAIL_USER=`echo ''|awk '{print ENVIRON["ch-sentry-email-user"]}'` +export SENTRY_EMAIL_PASSWORD=`echo ''|awk '{print ENVIRON["ch-sentry-email-password"]}'` # create / update database set -e @@ -43,4 +50,4 @@ echo "**** E:USR ****" echo "**** S:RUN ****" # run sentry sentry run web -echo "**** E:RUN ****" +echo "**** E:RUN ****" \ No newline at end of file diff --git a/applications/volumemanager/deploy/values.yaml b/applications/volumemanager/deploy/values.yaml index 8557ce18..ec5355ca 100644 --- a/applications/volumemanager/deploy/values.yaml +++ b/applications/volumemanager/deploy/values.yaml @@ -1,12 +1,15 @@ harness: + name: volumemanager + subdomain: volumemanager + service: + port: 8080 + auto: true name: volumemanager - subdomain: volumemanager - service: - port: 8080 - auto: true - name: volumemanager - secured: false - sentry: true - deployment: - auto: true - port: 8080 + secured: false + sentry: true + deployment: + auto: true + port: 8080 + dependencies: + build: + - cloudharness-flask diff --git a/applications/volumemanager/server/.dockerignore b/applications/volumemanager/server/.dockerignore index f9619601..a05d73b5 100644 --- a/applications/volumemanager/server/.dockerignore +++ b/applications/volumemanager/server/.dockerignore @@ -4,7 +4,6 @@ README.md tox.ini git_push.sh test-requirements.txt -setup.py # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/applications/volumemanager/server/Dockerfile b/applications/volumemanager/server/Dockerfile index 4a3039e2..e220778b 100644 --- a/applications/volumemanager/server/Dockerfile +++ b/applications/volumemanager/server/Dockerfile @@ -1,12 +1,13 @@ ARG REGISTRY ARG TAG=latest -FROM ${REGISTRY}cloudharness-base:${TAG} +ARG CLOUDHARNESS_FLASK=${REGISTRY}cloudharness-flask:${TAG} -RUN apk update -RUN apk upgrade +FROM $CLOUDHARNESS_FLASK as frontend -RUN mkdir -p /usr/src/app -WORKDIR /usr/src/app +ENV MODULE_NAME=volumemanager + +ENV WORKERS=2 +ENV PORT=8080 COPY requirements.txt /usr/src/app/ @@ -14,8 +15,6 @@ RUN pip3 install --no-cache-dir -r requirements.txt COPY . /usr/src/app -EXPOSE 8080 - -ENTRYPOINT ["python3"] +RUN pip3 install -e . -CMD ["-m", "volumemanager"] \ No newline at end of file +ENTRYPOINT gunicorn --workers=$WORKERS --bind=0.0.0.0:$PORT $MODULE_NAME.__main__:app diff --git a/applications/volumemanager/server/volumemanager/__main__.py b/applications/volumemanager/server/volumemanager/__main__.py index 866d5627..24522b72 100644 --- a/applications/volumemanager/server/volumemanager/__main__.py +++ b/applications/volumemanager/server/volumemanager/__main__.py @@ -1,18 +1,9 @@ #!/usr/bin/env python3 -import connexion +from cloudharness.utils.server import init_flask, main -from volumemanager import encoder - - -def main(): - app = connexion.App(__name__, specification_dir='./openapi/') - app.app.json_encoder = encoder.JSONEncoder - app.add_api('openapi.yaml', - arguments={'title': 'Volumes manager API'}, - pythonic_params=True) - app.run(port=8080) +app = init_flask(title="Volume manager") if __name__ == '__main__': main() diff --git a/applications/volumemanager/server/volumemanager/encoder.py b/applications/volumemanager/server/volumemanager/encoder.py deleted file mode 100644 index 50e16388..00000000 --- a/applications/volumemanager/server/volumemanager/encoder.py +++ /dev/null @@ -1,20 +0,0 @@ -from connexion.apps.flask_app import FlaskJSONEncoder -import six - -from volumemanager.models.base_model_ import Model - - -class JSONEncoder(FlaskJSONEncoder): - include_nulls = False - - def default(self, o): - if isinstance(o, Model): - dikt = {} - for attr, _ in six.iteritems(o.openapi_types): - value = getattr(o, attr) - if value is None and not self.include_nulls: - continue - attr = o.attribute_map[attr] - dikt[attr] = value - return dikt - return FlaskJSONEncoder.default(self, o) diff --git a/applications/workflows/api/workflows.yaml b/applications/workflows/api/workflows.yaml index 7290d295..1cadebdd 100644 --- a/applications/workflows/api/workflows.yaml +++ b/applications/workflows/api/workflows.yaml @@ -2,7 +2,7 @@ openapi: 3.0.0 servers: - description: Metacell host - url: https://workflows.cloudharness.metacell.us + url: https://workflows.cloudharness.metacell.us/api info: description: Workflows API diff --git a/applications/workflows/deploy/values.yaml b/applications/workflows/deploy/values.yaml index a53fb064..0867a2bd 100644 --- a/applications/workflows/deploy/values.yaml +++ b/applications/workflows/deploy/values.yaml @@ -6,4 +6,9 @@ harness: auto: true deployment: auto: true - port: 8080 \ No newline at end of file + port: 8080 + dependencies: + hard: + - argo + build: + - cloudharness-flask \ No newline at end of file diff --git a/applications/workflows/server/.dockerignore b/applications/workflows/server/.dockerignore index f9619601..a05d73b5 100644 --- a/applications/workflows/server/.dockerignore +++ b/applications/workflows/server/.dockerignore @@ -4,7 +4,6 @@ README.md tox.ini git_push.sh test-requirements.txt -setup.py # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/applications/workflows/server/Dockerfile b/applications/workflows/server/Dockerfile index 971916ec..b86556d1 100644 --- a/applications/workflows/server/Dockerfile +++ b/applications/workflows/server/Dockerfile @@ -1,18 +1,18 @@ ARG REGISTRY ARG TAG=latest -FROM ${REGISTRY}cloudharness-base:${TAG} +ARG CLOUDHARNESS_FLASK=${REGISTRY}cloudharness-flask:${TAG} -RUN mkdir -p /usr/src/app -WORKDIR /usr/src/app +FROM $CLOUDHARNESS_FLASK -COPY requirements.txt /usr/src/app/ +ENV MODULE_NAME=workflows_api + +COPY ./requirements.txt /usr/src/app/ RUN pip3 install --no-cache-dir -r requirements.txt COPY . /usr/src/app EXPOSE 8080 +RUN pip3 install -e . -ENTRYPOINT ["python3"] - -CMD ["-m", "workflows_api"] \ No newline at end of file +ENTRYPOINT gunicorn --workers=$WORKERS --bind=0.0.0.0:$PORT $MODULE_NAME.__main__:app \ No newline at end of file diff --git a/applications/workflows/server/requirements.txt b/applications/workflows/server/requirements.txt index 2639eedf..73c70d73 100644 --- a/applications/workflows/server/requirements.txt +++ b/applications/workflows/server/requirements.txt @@ -5,3 +5,4 @@ connexion == 2.4.0; python_version<="2.7" swagger-ui-bundle >= 0.0.2 python_dateutil >= 2.6.0 setuptools >= 21.0.0 +argo_workflows==5.0.0 diff --git a/applications/workflows/server/setup.py b/applications/workflows/server/setup.py index 9bd6a02e..b969a9de 100644 --- a/applications/workflows/server/setup.py +++ b/applications/workflows/server/setup.py @@ -16,7 +16,8 @@ REQUIRES = [ "connexion>=2.0.2", "swagger-ui-bundle>=0.0.2", - "python_dateutil>=2.6.0" + "python_dateutil>=2.6.0", + "argo_workflows" ] setup( diff --git a/applications/workflows/server/workflows_api/__main__.py b/applications/workflows/server/workflows_api/__main__.py index 40782233..a49051eb 100644 --- a/applications/workflows/server/workflows_api/__main__.py +++ b/applications/workflows/server/workflows_api/__main__.py @@ -1,18 +1,10 @@ #!/usr/bin/env python3 -import connexion - -from workflows_api import encoder - - -def main(): - app = connexion.App(__name__, specification_dir='./openapi/') - app.app.json_encoder = encoder.JSONEncoder - app.add_api('openapi.yaml', - arguments={'title': 'Workflows API'}, - pythonic_params=True) - app.run(port=8080) +from cloudharness.utils.server import init_flask, main +app = init_flask() if __name__ == '__main__': main() + + diff --git a/applications/workflows/server/workflows_api/controllers/create_and_access_controller.py b/applications/workflows/server/workflows_api/controllers/create_and_access_controller.py index c2f1f5d5..3b5c3ece 100644 --- a/applications/workflows/server/workflows_api/controllers/create_and_access_controller.py +++ b/applications/workflows/server/workflows_api/controllers/create_and_access_controller.py @@ -73,6 +73,7 @@ def list_operations(status=None, previous_search_token=None, limit=None): # noq log.error(f'Unhandled remote exception while retrieving workflows', exc_info=e) return '', e.status + def log_operation(name): # noqa: E501 """get operation by name @@ -85,6 +86,5 @@ def log_operation(name): # noqa: E501 """ if not name or name == '': return '' - - return workflow_service.log_operation(name) + return workflow_service.log_operation(name) diff --git a/applications/workflows/server/workflows_api/openapi/openapi.yaml b/applications/workflows/server/workflows_api/openapi/openapi.yaml index 05556983..1732df28 100644 --- a/applications/workflows/server/workflows_api/openapi/openapi.yaml +++ b/applications/workflows/server/workflows_api/openapi/openapi.yaml @@ -9,7 +9,7 @@ info: version: 0.1.0 servers: - description: Metacell host - url: https://workflows.cloudharness.metacell.us + url: https://workflows.cloudharness.metacell.us/api tags: - description: standard creation, listing and retrieve name: Create and Access diff --git a/applications/workflows/server/workflows_api/service/workflow_service.py b/applications/workflows/server/workflows_api/service/workflow_service.py index c0850410..69da77ad 100644 --- a/applications/workflows/server/workflows_api/service/workflow_service.py +++ b/applications/workflows/server/workflows_api/service/workflow_service.py @@ -7,8 +7,10 @@ def argo_workflow_to_operation(workflow: argo.Workflow): - return Operation(name=workflow.name, status=workflow.status, create_time=workflow.create_time, - workflow=workflow.raw) + return Operation(name=workflow.name, + status=workflow.status, + create_time=workflow.create_time, + workflow=workflow.raw.to_str()) def delete_operation(name): @@ -43,10 +45,10 @@ def list_operations(status=None, continue_token=None, limit=None) -> OperationSe return result -def log_operation(name:str) -> str: +def log_operation(name: str) -> str: """get operation logs :param name: workflow name :rtype: str """ - return argo.get_workflow_logs(name) \ No newline at end of file + return argo.get_workflow_logs(name) diff --git a/applications/workflows/tasks/extract-download/main.py b/applications/workflows/tasks/extract-download/main.py index 13bf858a..c519ee11 100644 --- a/applications/workflows/tasks/extract-download/main.py +++ b/applications/workflows/tasks/extract-download/main.py @@ -1,11 +1,9 @@ import urllib.request import sys -import logging +from cloudharness import log import os, stat from pathlib import Path -logging.basicConfig(stream=sys.stdout, level=logging.INFO) - assert len(sys.argv) > 2, 'Arguments not specified. Cannot download' url = sys.argv[1] @@ -21,25 +19,40 @@ dest = os.path.join(download_path, url.split('/')[-1]) -logging.info("Downloading {} to {}".format(url, dest)) +log.info("Downloading {} to {}".format(url, dest)) urllib.request.urlretrieve(url, dest) # test to see if the file is an zip archive import mimetypes + mime = mimetypes.MimeTypes().guess_type(dest)[0] + +mode_file = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH | stat.S_IWOTH # r+w g+o +mode_dir = mode_file | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH # for dirs also execute if mime == "application/zip": # extract it to the download_path folder import zipfile + with zipfile.ZipFile(dest, 'r') as zip_ref: zip_ref.extractall(download_path) - os.remove(dest) - -# TODO: may be a bit too drastic, may be only change the destination but how to handle the zip files where if there is a folder it is unknow -mode_file = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH | stat.S_IWOTH # r+w g+o -mode_dir = mode_file | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH # for dirs also execute -for dirpath, dirnames, filenames in os.walk(download_path): - os.chmod(dirpath, mode_dir) - for filename in filenames: - os.chmod(os.path.join(dirpath, filename), mode_file) - logging.info(f"chmod {dirpath}/{filename} to {mode_file}") + for fname in zip_ref.namelist(): + name = os.path.join(download_path, fname) + if os.path.isdir(name): + try: + os.chmod(name, mode_dir) + except: + log.warning("Cannot change folder permissions: %s", name, exc_info=True) + else: + try: + # log.info(f"chmod {dirpath}/{filename} to {mode_file}") + os.chmod(name, mode_file) + except: + log.warning("Cannot change file permissions: %s", name, exc_info=True) + os.remove(dest) +else: + try: + os.chmod(dest, mode_file) + except: + log.warning("Cannot change file permissions: %s", dest, exc_info=True) + diff --git a/applications/workflows/tasks/print-file/Dockerfile b/applications/workflows/tasks/print-file/Dockerfile index e25bd90f..6ce686cb 100644 --- a/applications/workflows/tasks/print-file/Dockerfile +++ b/applications/workflows/tasks/print-file/Dockerfile @@ -1,4 +1,6 @@ -FROM python:3.7-alpine +ARG REGISTRY +ARG TAG=latest +FROM ${REGISTRY}cloudharness-base:${TAG} ADD . / diff --git a/applications/workflows/tasks/print-file/main.py b/applications/workflows/tasks/print-file/main.py index d93a984c..57628d8c 100644 --- a/applications/workflows/tasks/print-file/main.py +++ b/applications/workflows/tasks/print-file/main.py @@ -1,15 +1,13 @@ -import urllib.request import sys -import logging import os -logging.basicConfig(stream=sys.stdout, level=logging.DEBUG) +from cloudharness import log assert len(sys.argv) > 1, 'File path not specified' file_path = sys.argv[1] -logging.info("Displaying content for file".format(file_path)) +log.info("Displaying content for file".format(file_path)) assert os.path.exists(file_path), file_path + " does not exist." with open(file_path) as f: print(f.read()) diff --git a/applications/workflows/tasks/send-result-event/main.py b/applications/workflows/tasks/send-result-event/main.py index 21134fa7..a8cad83c 100644 --- a/applications/workflows/tasks/send-result-event/main.py +++ b/applications/workflows/tasks/send-result-event/main.py @@ -3,6 +3,7 @@ print("Starting send-result-event") import glob from cloudharness import log, set_debug +from cloudharness.workflows.utils import notify_queue MAX_FILE_SIZE = 2 ** 20 # 1MB from cloudharness.events.client import EventClient @@ -21,7 +22,7 @@ log.info("Sending content of directory `{}` to event queue topic `{}`".format(shared_directory, topic_name)) -client = EventClient(topic_name) + assert os.path.exists(shared_directory), shared_directory + " does not exist." @@ -31,7 +32,7 @@ if size > MAX_FILE_SIZE: log.warning(f"{file_path} size is {size}, which is greater than the maximum of {MAX_FILE_SIZE}." "The content will not be sent to the queue") - client.produce({file_path: "Error: size exceeded"}) + notify_queue(topic_name, {file_path: "Error: size exceeded"}) log.info("Sending content for file `{}`".format(file_path)) try: @@ -41,4 +42,5 @@ log.error("Error reading file " + file_path + " " + str(e)) continue - client.produce({os.path.basename(file_path): content}) + + notify_queue(topic_name, {os.path.basename(file_path): content}) diff --git a/blueprint/application-templates/README.md b/blueprint/application-templates/README.md new file mode 100644 index 00000000..0b2923f7 --- /dev/null +++ b/blueprint/application-templates/README.md @@ -0,0 +1,7 @@ +# Application templates + +Add here all templates you want to merge/override +Follow the directory structure: +- base - those files are always added +- webapp - webapp scaffolding +- server - auto-generated server overriding files \ No newline at end of file diff --git a/client/cloudharness_cli/cloudharness_cli.egg-info/PKG-INFO b/client/cloudharness_cli/cloudharness_cli.egg-info/PKG-INFO deleted file mode 100644 index 7a3788ad..00000000 --- a/client/cloudharness_cli/cloudharness_cli.egg-info/PKG-INFO +++ /dev/null @@ -1,12 +0,0 @@ -Metadata-Version: 1.0 -Name: cloudharness-cli -Version: 0.1.0 -Summary: CloudHarness Python API Client -Home-page: UNKNOWN -Author: OpenAPI Generator community -Author-email: cloudharness@metacell.us -License: UNLICENSED -Description: CloudHarness Python API Client # noqa: E501 - -Keywords: OpenAPI,CloudHarness Sample API -Platform: UNKNOWN diff --git a/client/cloudharness_cli/cloudharness_cli.egg-info/SOURCES.txt b/client/cloudharness_cli/cloudharness_cli.egg-info/SOURCES.txt deleted file mode 100644 index ce02554f..00000000 --- a/client/cloudharness_cli/cloudharness_cli.egg-info/SOURCES.txt +++ /dev/null @@ -1,40 +0,0 @@ -README.md -setup.py -cloudharness_cli/__init__.py -cloudharness_cli.egg-info/PKG-INFO -cloudharness_cli.egg-info/SOURCES.txt -cloudharness_cli.egg-info/dependency_links.txt -cloudharness_cli.egg-info/requires.txt -cloudharness_cli.egg-info/top_level.txt -cloudharness_cli/common/__init__.py -cloudharness_cli/common/api_client.py -cloudharness_cli/common/configuration.py -cloudharness_cli/common/exceptions.py -cloudharness_cli/common/rest.py -cloudharness_cli/common/api/__init__.py -cloudharness_cli/common/api/sentry_api.py -cloudharness_cli/common/models/__init__.py -cloudharness_cli/samples/__init__.py -cloudharness_cli/samples/api_client.py -cloudharness_cli/samples/configuration.py -cloudharness_cli/samples/exceptions.py -cloudharness_cli/samples/rest.py -cloudharness_cli/samples/api/__init__.py -cloudharness_cli/samples/api/auth_api.py -cloudharness_cli/samples/api/workflows_api.py -cloudharness_cli/samples/models/__init__.py -cloudharness_cli/samples/models/inline_response202.py -cloudharness_cli/samples/models/inline_response202_task.py -cloudharness_cli/samples/models/valid.py -cloudharness_cli/workflows/__init__.py -cloudharness_cli/workflows/api_client.py -cloudharness_cli/workflows/configuration.py -cloudharness_cli/workflows/exceptions.py -cloudharness_cli/workflows/rest.py -cloudharness_cli/workflows/api/__init__.py -cloudharness_cli/workflows/api/create_and_access_api.py -cloudharness_cli/workflows/models/__init__.py -cloudharness_cli/workflows/models/operation.py -cloudharness_cli/workflows/models/operation_search_result.py -cloudharness_cli/workflows/models/operation_status.py -cloudharness_cli/workflows/models/search_result_data.py \ No newline at end of file diff --git a/client/cloudharness_cli/cloudharness_cli.egg-info/dependency_links.txt b/client/cloudharness_cli/cloudharness_cli.egg-info/dependency_links.txt deleted file mode 100644 index 8b137891..00000000 --- a/client/cloudharness_cli/cloudharness_cli.egg-info/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/client/cloudharness_cli/cloudharness_cli.egg-info/requires.txt b/client/cloudharness_cli/cloudharness_cli.egg-info/requires.txt deleted file mode 100644 index 17318e9a..00000000 --- a/client/cloudharness_cli/cloudharness_cli.egg-info/requires.txt +++ /dev/null @@ -1,4 +0,0 @@ -urllib3>=1.15 -six>=1.10 -certifi -python-dateutil diff --git a/client/cloudharness_cli/cloudharness_cli.egg-info/top_level.txt b/client/cloudharness_cli/cloudharness_cli.egg-info/top_level.txt deleted file mode 100644 index beb24983..00000000 --- a/client/cloudharness_cli/cloudharness_cli.egg-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -cloudharness_cli diff --git a/infrastructure/base-images/cloudharness-base-debian/Dockerfile b/infrastructure/base-images/cloudharness-base-debian/Dockerfile index 2602fda6..62d9854c 100644 --- a/infrastructure/base-images/cloudharness-base-debian/Dockerfile +++ b/infrastructure/base-images/cloudharness-base-debian/Dockerfile @@ -1,8 +1,15 @@ ARG PARENT=python:3.7.6 FROM ${PARENT} +COPY libraries/cloudharness-common/requirements.txt /libraries/cloudharness-common/requirements.txt +RUN pip install -r /libraries/cloudharness-common/requirements.txt +COPY libraries/client/cloudharness_cli/requirements.txt /libraries/client/cloudharness_cli/requirements.txt +RUN pip install -r /libraries/client/cloudharness_cli/requirements.txt + COPY libraries/cloudharness-common /libraries/cloudharness-common +COPY libraries/client/cloudharness_cli /libraries/client/cloudharness_cli -RUN pip install /libraries/cloudharness-common +RUN pip install -e /libraries/cloudharness-common +RUN pip install -e /libraries/client/cloudharness_cli WORKDIR / \ No newline at end of file diff --git a/infrastructure/base-images/cloudharness-base/Dockerfile b/infrastructure/base-images/cloudharness-base/Dockerfile index 582cdad9..66fc3dd4 100644 --- a/infrastructure/base-images/cloudharness-base/Dockerfile +++ b/infrastructure/base-images/cloudharness-base/Dockerfile @@ -1,4 +1,4 @@ -ARG PARENT=python:3.7.6-alpine +ARG PARENT=python:3.7.9-alpine FROM ${PARENT} RUN apk update @@ -7,12 +7,17 @@ RUN apk upgrade # Add bash for k8s console RUN apk add bash # dev tools needed by some python libraries -RUN apk add gcc libc-dev g++ python3-dev libffi-dev openssl-dev +RUN apk add gcc libc-dev g++ python3-dev libffi-dev openssl-dev rust musl-dev cargo +COPY libraries/cloudharness-common/requirements.txt /libraries/cloudharness-common/requirements.txt +RUN pip install -r /libraries/cloudharness-common/requirements.txt +COPY libraries/client/cloudharness_cli/requirements.txt /libraries/client/cloudharness_cli/requirements.txt +RUN pip install -r /libraries/client/cloudharness_cli/requirements.txt COPY libraries/cloudharness-common /libraries/cloudharness-common -COPY client/cloudharness_cli /client/cloudharness_cli +COPY libraries/client/cloudharness_cli /libraries/client/cloudharness_cli -RUN pip install /libraries/cloudharness-common -RUN pip install /client/cloudharness_cli +# +RUN pip install -e /libraries/cloudharness-common +RUN pip install -e /libraries/client/cloudharness_cli -WORKDIR / \ No newline at end of file +WORKDIR / diff --git a/infrastructure/base-images/cloudharness-frontend-build/Dockerfile b/infrastructure/base-images/cloudharness-frontend-build/Dockerfile new file mode 100644 index 00000000..ec4c5990 --- /dev/null +++ b/infrastructure/base-images/cloudharness-frontend-build/Dockerfile @@ -0,0 +1,3 @@ +FROM node:15.5 + + diff --git a/infrastructure/base-images/cloudharness-frontend-build/README.md b/infrastructure/base-images/cloudharness-frontend-build/README.md new file mode 100644 index 00000000..0b34f0de --- /dev/null +++ b/infrastructure/base-images/cloudharness-frontend-build/README.md @@ -0,0 +1,3 @@ +# Cloudharness frontend Base image + +Use this image to build your frontend images diff --git a/infrastructure/cluster-configuration/README.md b/infrastructure/cluster-configuration/README.md new file mode 100644 index 00000000..a96d972e --- /dev/null +++ b/infrastructure/cluster-configuration/README.md @@ -0,0 +1,4 @@ +# Cluster configuration + +1. Initialize kubectl credentials to work with your cluster (e.g minikube or google cloud) +1. Run `source cluster-init.sh` \ No newline at end of file diff --git a/infrastructure/cluster-configuration/cluster-init.sh b/infrastructure/cluster-configuration/cluster-init.sh new file mode 100644 index 00000000..bf9a7f5f --- /dev/null +++ b/infrastructure/cluster-configuration/cluster-init.sh @@ -0,0 +1,3 @@ +helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx +helm repo update +helm install ingress ingress-nginx/ingress-nginx -f ingress/values.yaml -n kube-system \ No newline at end of file diff --git a/infrastructure/cluster-configuration/ingress/values.yaml b/infrastructure/cluster-configuration/ingress/values.yaml new file mode 100644 index 00000000..863dc408 --- /dev/null +++ b/infrastructure/cluster-configuration/ingress/values.yaml @@ -0,0 +1,7 @@ +controller: + config: + http-snippet: | + proxy_cache_path /tmp/nginx-cache levels=1:2 keys_zone=static-cache:2m max_size=100m inactive=7d use_temp_path=off; + proxy_cache_key $scheme$proxy_host$request_uri; + proxy_cache_lock on; + proxy_cache_use_stale updating; \ No newline at end of file diff --git a/infrastructure/cluster-configuration/storageclass.yaml b/infrastructure/cluster-configuration/storageclass.yaml new file mode 100644 index 00000000..97e42d96 --- /dev/null +++ b/infrastructure/cluster-configuration/storageclass.yaml @@ -0,0 +1,8 @@ +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: persisted +reclaimPolicy: Retain +volumeProvisioner: kubernetes.io/gce-pd +volumeBindingMode: Immediate +--- \ No newline at end of file diff --git a/infrastructure/common-images/cloudharness-flask/Dockerfile b/infrastructure/common-images/cloudharness-flask/Dockerfile new file mode 100644 index 00000000..91aa2f02 --- /dev/null +++ b/infrastructure/common-images/cloudharness-flask/Dockerfile @@ -0,0 +1,19 @@ +ARG REGISTRY +ARG TAG=latest +FROM ${REGISTRY}cloudharness-base:${TAG} + +ENV DIR=/usr/src/app +# Override module name in sub image +ENV MODULE_NAME=app +ENV WORKERS=2 +ENV PORT=8080 + +WORKDIR $DIR + +# install dependencies +RUN pip install --upgrade pip +COPY ./requirements.txt requirements.txt +RUN pip install --no-cache-dir -r requirements.txt + +EXPOSE $PORT +ENTRYPOINT gunicorn --workers=$WORKERS --bind=0.0.0.0:$PORT $MODULE_NAME.__main__:app \ No newline at end of file diff --git a/infrastructure/common-images/cloudharness-flask/requirements.txt b/infrastructure/common-images/cloudharness-flask/requirements.txt new file mode 100644 index 00000000..fb164737 --- /dev/null +++ b/infrastructure/common-images/cloudharness-flask/requirements.txt @@ -0,0 +1,6 @@ +gunicorn>=20.0.4 +flask>=1.0.2 +connexion == 2.7.0 +swagger-ui-bundle == 0.0.8 +python_dateutil >= 2.6.0 +setuptools >= 21.0.0 \ No newline at end of file diff --git a/client/cloudharness_cli/README.md b/libraries/client/cloudharness_cli/README.md similarity index 100% rename from client/cloudharness_cli/README.md rename to libraries/client/cloudharness_cli/README.md diff --git a/applications/samples/server/api_samples/service/__init__.py b/libraries/client/cloudharness_cli/cloudharness_cli/__init__.py similarity index 100% rename from applications/samples/server/api_samples/service/__init__.py rename to libraries/client/cloudharness_cli/cloudharness_cli/__init__.py diff --git a/client/cloudharness_cli/cloudharness_cli/common/__init__.py b/libraries/client/cloudharness_cli/cloudharness_cli/common/__init__.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/common/__init__.py rename to libraries/client/cloudharness_cli/cloudharness_cli/common/__init__.py diff --git a/client/cloudharness_cli/cloudharness_cli/common/api/__init__.py b/libraries/client/cloudharness_cli/cloudharness_cli/common/api/__init__.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/common/api/__init__.py rename to libraries/client/cloudharness_cli/cloudharness_cli/common/api/__init__.py diff --git a/client/cloudharness_cli/cloudharness_cli/common/api/sentry_api.py b/libraries/client/cloudharness_cli/cloudharness_cli/common/api/sentry_api.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/common/api/sentry_api.py rename to libraries/client/cloudharness_cli/cloudharness_cli/common/api/sentry_api.py diff --git a/client/cloudharness_cli/cloudharness_cli/common/api_client.py b/libraries/client/cloudharness_cli/cloudharness_cli/common/api_client.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/common/api_client.py rename to libraries/client/cloudharness_cli/cloudharness_cli/common/api_client.py diff --git a/client/cloudharness_cli/cloudharness_cli/common/configuration.py b/libraries/client/cloudharness_cli/cloudharness_cli/common/configuration.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/common/configuration.py rename to libraries/client/cloudharness_cli/cloudharness_cli/common/configuration.py diff --git a/client/cloudharness_cli/cloudharness_cli/common/exceptions.py b/libraries/client/cloudharness_cli/cloudharness_cli/common/exceptions.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/common/exceptions.py rename to libraries/client/cloudharness_cli/cloudharness_cli/common/exceptions.py diff --git a/client/cloudharness_cli/cloudharness_cli/common/models/__init__.py b/libraries/client/cloudharness_cli/cloudharness_cli/common/models/__init__.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/common/models/__init__.py rename to libraries/client/cloudharness_cli/cloudharness_cli/common/models/__init__.py diff --git a/client/cloudharness_cli/cloudharness_cli/common/rest.py b/libraries/client/cloudharness_cli/cloudharness_cli/common/rest.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/common/rest.py rename to libraries/client/cloudharness_cli/cloudharness_cli/common/rest.py diff --git a/client/cloudharness_cli/cloudharness_cli/samples/__init__.py b/libraries/client/cloudharness_cli/cloudharness_cli/samples/__init__.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/samples/__init__.py rename to libraries/client/cloudharness_cli/cloudharness_cli/samples/__init__.py diff --git a/client/cloudharness_cli/cloudharness_cli/samples/api/__init__.py b/libraries/client/cloudharness_cli/cloudharness_cli/samples/api/__init__.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/samples/api/__init__.py rename to libraries/client/cloudharness_cli/cloudharness_cli/samples/api/__init__.py diff --git a/client/cloudharness_cli/cloudharness_cli/samples/api/auth_api.py b/libraries/client/cloudharness_cli/cloudharness_cli/samples/api/auth_api.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/samples/api/auth_api.py rename to libraries/client/cloudharness_cli/cloudharness_cli/samples/api/auth_api.py diff --git a/client/cloudharness_cli/cloudharness_cli/samples/api/workflows_api.py b/libraries/client/cloudharness_cli/cloudharness_cli/samples/api/workflows_api.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/samples/api/workflows_api.py rename to libraries/client/cloudharness_cli/cloudharness_cli/samples/api/workflows_api.py diff --git a/client/cloudharness_cli/cloudharness_cli/samples/api_client.py b/libraries/client/cloudharness_cli/cloudharness_cli/samples/api_client.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/samples/api_client.py rename to libraries/client/cloudharness_cli/cloudharness_cli/samples/api_client.py diff --git a/client/cloudharness_cli/cloudharness_cli/samples/configuration.py b/libraries/client/cloudharness_cli/cloudharness_cli/samples/configuration.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/samples/configuration.py rename to libraries/client/cloudharness_cli/cloudharness_cli/samples/configuration.py diff --git a/client/cloudharness_cli/cloudharness_cli/samples/exceptions.py b/libraries/client/cloudharness_cli/cloudharness_cli/samples/exceptions.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/samples/exceptions.py rename to libraries/client/cloudharness_cli/cloudharness_cli/samples/exceptions.py diff --git a/client/cloudharness_cli/cloudharness_cli/samples/models/__init__.py b/libraries/client/cloudharness_cli/cloudharness_cli/samples/models/__init__.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/samples/models/__init__.py rename to libraries/client/cloudharness_cli/cloudharness_cli/samples/models/__init__.py diff --git a/client/cloudharness_cli/cloudharness_cli/samples/models/inline_response202.py b/libraries/client/cloudharness_cli/cloudharness_cli/samples/models/inline_response202.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/samples/models/inline_response202.py rename to libraries/client/cloudharness_cli/cloudharness_cli/samples/models/inline_response202.py diff --git a/client/cloudharness_cli/cloudharness_cli/samples/models/inline_response202_task.py b/libraries/client/cloudharness_cli/cloudharness_cli/samples/models/inline_response202_task.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/samples/models/inline_response202_task.py rename to libraries/client/cloudharness_cli/cloudharness_cli/samples/models/inline_response202_task.py diff --git a/client/cloudharness_cli/cloudharness_cli/samples/models/valid.py b/libraries/client/cloudharness_cli/cloudharness_cli/samples/models/valid.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/samples/models/valid.py rename to libraries/client/cloudharness_cli/cloudharness_cli/samples/models/valid.py diff --git a/client/cloudharness_cli/cloudharness_cli/samples/rest.py b/libraries/client/cloudharness_cli/cloudharness_cli/samples/rest.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/samples/rest.py rename to libraries/client/cloudharness_cli/cloudharness_cli/samples/rest.py diff --git a/client/cloudharness_cli/cloudharness_cli/workflows/__init__.py b/libraries/client/cloudharness_cli/cloudharness_cli/workflows/__init__.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/workflows/__init__.py rename to libraries/client/cloudharness_cli/cloudharness_cli/workflows/__init__.py diff --git a/client/cloudharness_cli/cloudharness_cli/workflows/api/__init__.py b/libraries/client/cloudharness_cli/cloudharness_cli/workflows/api/__init__.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/workflows/api/__init__.py rename to libraries/client/cloudharness_cli/cloudharness_cli/workflows/api/__init__.py diff --git a/client/cloudharness_cli/cloudharness_cli/workflows/api/create_and_access_api.py b/libraries/client/cloudharness_cli/cloudharness_cli/workflows/api/create_and_access_api.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/workflows/api/create_and_access_api.py rename to libraries/client/cloudharness_cli/cloudharness_cli/workflows/api/create_and_access_api.py diff --git a/client/cloudharness_cli/cloudharness_cli/workflows/api_client.py b/libraries/client/cloudharness_cli/cloudharness_cli/workflows/api_client.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/workflows/api_client.py rename to libraries/client/cloudharness_cli/cloudharness_cli/workflows/api_client.py diff --git a/client/cloudharness_cli/cloudharness_cli/workflows/configuration.py b/libraries/client/cloudharness_cli/cloudharness_cli/workflows/configuration.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/workflows/configuration.py rename to libraries/client/cloudharness_cli/cloudharness_cli/workflows/configuration.py diff --git a/client/cloudharness_cli/cloudharness_cli/workflows/exceptions.py b/libraries/client/cloudharness_cli/cloudharness_cli/workflows/exceptions.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/workflows/exceptions.py rename to libraries/client/cloudharness_cli/cloudharness_cli/workflows/exceptions.py diff --git a/client/cloudharness_cli/cloudharness_cli/workflows/models/__init__.py b/libraries/client/cloudharness_cli/cloudharness_cli/workflows/models/__init__.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/workflows/models/__init__.py rename to libraries/client/cloudharness_cli/cloudharness_cli/workflows/models/__init__.py diff --git a/client/cloudharness_cli/cloudharness_cli/workflows/models/operation.py b/libraries/client/cloudharness_cli/cloudharness_cli/workflows/models/operation.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/workflows/models/operation.py rename to libraries/client/cloudharness_cli/cloudharness_cli/workflows/models/operation.py diff --git a/client/cloudharness_cli/cloudharness_cli/workflows/models/operation_search_result.py b/libraries/client/cloudharness_cli/cloudharness_cli/workflows/models/operation_search_result.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/workflows/models/operation_search_result.py rename to libraries/client/cloudharness_cli/cloudharness_cli/workflows/models/operation_search_result.py diff --git a/client/cloudharness_cli/cloudharness_cli/workflows/models/operation_status.py b/libraries/client/cloudharness_cli/cloudharness_cli/workflows/models/operation_status.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/workflows/models/operation_status.py rename to libraries/client/cloudharness_cli/cloudharness_cli/workflows/models/operation_status.py diff --git a/client/cloudharness_cli/cloudharness_cli/workflows/models/search_result_data.py b/libraries/client/cloudharness_cli/cloudharness_cli/workflows/models/search_result_data.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/workflows/models/search_result_data.py rename to libraries/client/cloudharness_cli/cloudharness_cli/workflows/models/search_result_data.py diff --git a/client/cloudharness_cli/cloudharness_cli/workflows/rest.py b/libraries/client/cloudharness_cli/cloudharness_cli/workflows/rest.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/workflows/rest.py rename to libraries/client/cloudharness_cli/cloudharness_cli/workflows/rest.py diff --git a/client/cloudharness_cli/docs/common/SentryApi.md b/libraries/client/cloudharness_cli/docs/common/SentryApi.md similarity index 100% rename from client/cloudharness_cli/docs/common/SentryApi.md rename to libraries/client/cloudharness_cli/docs/common/SentryApi.md diff --git a/client/cloudharness_cli/docs/samples/AuthApi.md b/libraries/client/cloudharness_cli/docs/samples/AuthApi.md similarity index 100% rename from client/cloudharness_cli/docs/samples/AuthApi.md rename to libraries/client/cloudharness_cli/docs/samples/AuthApi.md diff --git a/client/cloudharness_cli/docs/samples/InlineResponse202.md b/libraries/client/cloudharness_cli/docs/samples/InlineResponse202.md similarity index 100% rename from client/cloudharness_cli/docs/samples/InlineResponse202.md rename to libraries/client/cloudharness_cli/docs/samples/InlineResponse202.md diff --git a/client/cloudharness_cli/docs/samples/InlineResponse202Task.md b/libraries/client/cloudharness_cli/docs/samples/InlineResponse202Task.md similarity index 100% rename from client/cloudharness_cli/docs/samples/InlineResponse202Task.md rename to libraries/client/cloudharness_cli/docs/samples/InlineResponse202Task.md diff --git a/client/cloudharness_cli/docs/samples/Valid.md b/libraries/client/cloudharness_cli/docs/samples/Valid.md similarity index 100% rename from client/cloudharness_cli/docs/samples/Valid.md rename to libraries/client/cloudharness_cli/docs/samples/Valid.md diff --git a/client/cloudharness_cli/docs/samples/WorkflowsApi.md b/libraries/client/cloudharness_cli/docs/samples/WorkflowsApi.md similarity index 100% rename from client/cloudharness_cli/docs/samples/WorkflowsApi.md rename to libraries/client/cloudharness_cli/docs/samples/WorkflowsApi.md diff --git a/client/cloudharness_cli/docs/workflows/CreateAndAccessApi.md b/libraries/client/cloudharness_cli/docs/workflows/CreateAndAccessApi.md similarity index 100% rename from client/cloudharness_cli/docs/workflows/CreateAndAccessApi.md rename to libraries/client/cloudharness_cli/docs/workflows/CreateAndAccessApi.md diff --git a/client/cloudharness_cli/docs/workflows/Operation.md b/libraries/client/cloudharness_cli/docs/workflows/Operation.md similarity index 100% rename from client/cloudharness_cli/docs/workflows/Operation.md rename to libraries/client/cloudharness_cli/docs/workflows/Operation.md diff --git a/client/cloudharness_cli/docs/workflows/OperationSearchResult.md b/libraries/client/cloudharness_cli/docs/workflows/OperationSearchResult.md similarity index 100% rename from client/cloudharness_cli/docs/workflows/OperationSearchResult.md rename to libraries/client/cloudharness_cli/docs/workflows/OperationSearchResult.md diff --git a/client/cloudharness_cli/docs/workflows/OperationStatus.md b/libraries/client/cloudharness_cli/docs/workflows/OperationStatus.md similarity index 100% rename from client/cloudharness_cli/docs/workflows/OperationStatus.md rename to libraries/client/cloudharness_cli/docs/workflows/OperationStatus.md diff --git a/client/cloudharness_cli/docs/workflows/SearchResultData.md b/libraries/client/cloudharness_cli/docs/workflows/SearchResultData.md similarity index 100% rename from client/cloudharness_cli/docs/workflows/SearchResultData.md rename to libraries/client/cloudharness_cli/docs/workflows/SearchResultData.md diff --git a/client/cloudharness_cli/requirements.txt b/libraries/client/cloudharness_cli/requirements.txt similarity index 100% rename from client/cloudharness_cli/requirements.txt rename to libraries/client/cloudharness_cli/requirements.txt diff --git a/client/cloudharness_cli/setup.py b/libraries/client/cloudharness_cli/setup.py similarity index 100% rename from client/cloudharness_cli/setup.py rename to libraries/client/cloudharness_cli/setup.py diff --git a/client/cloudharness_cli/test-requirements.txt b/libraries/client/cloudharness_cli/test-requirements.txt similarity index 100% rename from client/cloudharness_cli/test-requirements.txt rename to libraries/client/cloudharness_cli/test-requirements.txt diff --git a/applications/workflows/server/__init__.py b/libraries/client/cloudharness_cli/test/common/__init__.py similarity index 100% rename from applications/workflows/server/__init__.py rename to libraries/client/cloudharness_cli/test/common/__init__.py diff --git a/client/cloudharness_cli/test/common/test_sentry_api.py b/libraries/client/cloudharness_cli/test/common/test_sentry_api.py similarity index 100% rename from client/cloudharness_cli/test/common/test_sentry_api.py rename to libraries/client/cloudharness_cli/test/common/test_sentry_api.py diff --git a/client/cloudharness_cli/cloudharness_cli/__init__.py b/libraries/client/cloudharness_cli/test/samples/__init__.py similarity index 100% rename from client/cloudharness_cli/cloudharness_cli/__init__.py rename to libraries/client/cloudharness_cli/test/samples/__init__.py diff --git a/client/cloudharness_cli/test/samples/test_auth_api.py b/libraries/client/cloudharness_cli/test/samples/test_auth_api.py similarity index 100% rename from client/cloudharness_cli/test/samples/test_auth_api.py rename to libraries/client/cloudharness_cli/test/samples/test_auth_api.py diff --git a/client/cloudharness_cli/test/samples/test_inline_response202.py b/libraries/client/cloudharness_cli/test/samples/test_inline_response202.py similarity index 100% rename from client/cloudharness_cli/test/samples/test_inline_response202.py rename to libraries/client/cloudharness_cli/test/samples/test_inline_response202.py diff --git a/client/cloudharness_cli/test/samples/test_inline_response202_task.py b/libraries/client/cloudharness_cli/test/samples/test_inline_response202_task.py similarity index 100% rename from client/cloudharness_cli/test/samples/test_inline_response202_task.py rename to libraries/client/cloudharness_cli/test/samples/test_inline_response202_task.py diff --git a/client/cloudharness_cli/test/samples/test_valid.py b/libraries/client/cloudharness_cli/test/samples/test_valid.py similarity index 100% rename from client/cloudharness_cli/test/samples/test_valid.py rename to libraries/client/cloudharness_cli/test/samples/test_valid.py diff --git a/client/cloudharness_cli/test/samples/test_workflows_api.py b/libraries/client/cloudharness_cli/test/samples/test_workflows_api.py similarity index 100% rename from client/cloudharness_cli/test/samples/test_workflows_api.py rename to libraries/client/cloudharness_cli/test/samples/test_workflows_api.py diff --git a/client/cloudharness_cli/test/common/__init__.py b/libraries/client/cloudharness_cli/test/workflows/__init__.py similarity index 100% rename from client/cloudharness_cli/test/common/__init__.py rename to libraries/client/cloudharness_cli/test/workflows/__init__.py diff --git a/client/cloudharness_cli/test/workflows/test_create_and_access_api.py b/libraries/client/cloudharness_cli/test/workflows/test_create_and_access_api.py similarity index 100% rename from client/cloudharness_cli/test/workflows/test_create_and_access_api.py rename to libraries/client/cloudharness_cli/test/workflows/test_create_and_access_api.py diff --git a/client/cloudharness_cli/test/workflows/test_operation.py b/libraries/client/cloudharness_cli/test/workflows/test_operation.py similarity index 100% rename from client/cloudharness_cli/test/workflows/test_operation.py rename to libraries/client/cloudharness_cli/test/workflows/test_operation.py diff --git a/client/cloudharness_cli/test/workflows/test_operation_search_result.py b/libraries/client/cloudharness_cli/test/workflows/test_operation_search_result.py similarity index 100% rename from client/cloudharness_cli/test/workflows/test_operation_search_result.py rename to libraries/client/cloudharness_cli/test/workflows/test_operation_search_result.py diff --git a/client/cloudharness_cli/test/workflows/test_operation_status.py b/libraries/client/cloudharness_cli/test/workflows/test_operation_status.py similarity index 100% rename from client/cloudharness_cli/test/workflows/test_operation_status.py rename to libraries/client/cloudharness_cli/test/workflows/test_operation_status.py diff --git a/client/cloudharness_cli/test/workflows/test_search_result_data.py b/libraries/client/cloudharness_cli/test/workflows/test_search_result_data.py similarity index 100% rename from client/cloudharness_cli/test/workflows/test_search_result_data.py rename to libraries/client/cloudharness_cli/test/workflows/test_search_result_data.py diff --git a/libraries/cloudharness-common/cloudharness/__init__.py b/libraries/cloudharness-common/cloudharness/__init__.py index 438eae54..bc32095a 100644 --- a/libraries/cloudharness-common/cloudharness/__init__.py +++ b/libraries/cloudharness-common/cloudharness/__init__.py @@ -3,7 +3,8 @@ log = logging -# logging.basicConfig(stream=sys.stdout, level=logging.INFO) +FORMAT = "%(asctime)s [%(levelname)s] %(module)s.%(funcName)s: %(message)s" +logging.basicConfig(stream=sys.stdout, format=FORMAT, level=logging.INFO) def set_debug(): logging.basicConfig(stream=sys.stdout, level=logging.DEBUG) @@ -35,3 +36,4 @@ def init(appname: str): log.warning(f'Error enabling Sentry for {appname}', exc_info=True) __all__ = ['log', 'init'] + diff --git a/libraries/cloudharness-common/cloudharness/applications.py b/libraries/cloudharness-common/cloudharness/applications.py index 7e9c1286..94680b68 100644 --- a/libraries/cloudharness-common/cloudharness/applications.py +++ b/libraries/cloudharness-common/cloudharness/applications.py @@ -1,5 +1,6 @@ from cloudharness.utils.config import CloudharnessConfig, ConfigObject +class ConfigurationCallException(Exception): pass class ApplicationConfiguration: @@ -8,12 +9,19 @@ def __init__(self, conf_dict_or_config_object): self.conf = ConfigObject(conf_dict_or_config_object) else: self.conf = conf_dict_or_config_object - self.name = self.conf.name - self.harness = self.conf.harness + + + @property + def name(self): + return self['harness.name'] + + @property + def harness(self): + return self.conf.harness def __getitem__(self, key_or_path): item = self.conf[key_or_path] - if (isinstance(item, ConfigObject) or isinstance(item, dict)) and item['harness']: + if (isinstance(item, ConfigObject) or isinstance(item, dict)) and 'harness' in item and item['harness']: item = ApplicationConfiguration(item) return item @@ -26,17 +34,59 @@ def is_auto_service(self): def is_auto_deployment(self): return self['harness.deployment.auto'] + def is_auto_db(self): + return self['harness.database.auto'] + def is_sentry_enabled(self): return self['harness.sentry'] + def get_db_connection_string(self): + if not self.is_auto_db(): + raise ConfigurationCallException(f"Cannot get configuration string: application {self.name} has no database enabled.") + if self.db_type == 'mongo': + return f"mongodb://{self['harness.database.user']}:{self['harness.database.pass']}@{self.db_name}:{self['harness.database.mongo.ports'][0]['port']}/" + else: + raise NotImplementedError(f'Database connection string discovery not yet supported for databse type {self.db_type}') + + @property + def db_name(self): + return self['harness.database.name'] + + @property + def db_type(self): + return self['harness.database.type'] + @property + def service_name(self): + name = self['harness.service.name'] + if not name: + raise ConfigurationCallException(f"Cannot get service address for {self.name}: auto service is not enabled") + return name + + @property + def service_port(self): + port = self['harness.service.port'] + if not port: + raise ConfigurationCallException(f"Cannot get service port for {self.name}: auto service is not enabled") + return port + + def get_service_address(self): + return f"http://{self.service_name}.{CloudharnessConfig.get_namespace()}:{self.service_port}" + + def get_public_address(self): + + if not self['harness.subdomain']: + raise ConfigurationCallException(f"Cannot get public address for {self.name}: no subdomain is specified for this appplication.") + return f"http{'s' if CloudharnessConfig.is_secured() else ''}://{self['harness.subdomain']}.{CloudharnessConfig.get_domain()}" def get_configurations(**kwargs): return [ApplicationConfiguration(conf) for conf in CloudharnessConfig.get_application_by_filter(**kwargs)] -def get_configuration(app_name): - conf = CloudharnessConfig.get_application_by_filter(name=app_name) - if conf: - if len(conf) > 1: - raise Exception(f'More than one app with the same name is not allowed. Found {len(conf)} applications with name {app_name}') - return ApplicationConfiguration(conf[0]) +def get_configuration(app_name) -> ApplicationConfiguration: + conf = CloudharnessConfig.get_application_by_filter(harness__name=app_name) + if len(conf) > 1: + raise ConfigurationCallException(f'Application {app_name} is not unique inside the current deployment.') + if not conf: + raise ConfigurationCallException(f'Application {app_name} is not part of the current deployment.') + return ApplicationConfiguration(conf[0]) + diff --git a/libraries/cloudharness-common/cloudharness/auth/keycloak/__init__.py b/libraries/cloudharness-common/cloudharness/auth/keycloak/__init__.py index 7d454a94..01a7d4ee 100644 --- a/libraries/cloudharness-common/cloudharness/auth/keycloak/__init__.py +++ b/libraries/cloudharness-common/cloudharness/auth/keycloak/__init__.py @@ -1,37 +1,36 @@ import os import jwt -import sys import json import requests -from urllib.parse import urljoin -from typing import List from flask import current_app, request from keycloak import KeycloakAdmin from keycloak.exceptions import KeycloakAuthenticationError - -from typing import List -from urllib.parse import urljoin - +from cloudharness import log from cloudharness.utils import env try: - from cloudharness.utils.config import CloudharnessConfig as conf - accounts_app = conf.get_application_by_filter(name='accounts')[0] + from cloudharness.utils.config import CloudharnessConfig as conf, ALLVALUES_PATH + from cloudharness.applications import get_configuration + accounts_app = get_configuration('accounts') AUTH_REALM = env.get_auth_realm() - SCHEMA = 'http' - HOST = getattr(accounts_app,'subdomain') - PORT = getattr(accounts_app,'port') - USER = getattr(accounts_app.admin,'user') - PASSWD = getattr(accounts_app.admin,'pass') + SERVER_URL = accounts_app.get_service_address() + '/auth/' + if not os.environ.get('KUBERNETES_SERVICE_HOST', None): + # running outside kubernetes + SERVER_URL = accounts_app.get_public_address() + '/auth/' + USER = accounts_app.admin['user'] + PASSWD = accounts_app.admin['pass'] except: - AUTH_REALM = 'mnp' - SCHEMA = 'https' - HOST = 'accounts.mnp.metacell.us' - PORT = '443' - USER = 'mnp' - PASSWD = 'metacell' + log.error("Error on cloudharness configuration. Check that the values file %s your deployment.", ALLVALUES_PATH, exc_info=True) -SERVER_URL = f'{SCHEMA}://{HOST}:{PORT}/auth/' + +def with_refreshtoken(func): + def wrapper(self, *args, **kwargs): + try: + return func(self, *args, **kwargs) + except KeycloakAuthenticationError: + self.refresh_token() + return func(self, *args, **kwargs) + return wrapper def decode_token(token): """ @@ -52,6 +51,7 @@ def decode_token(token): class AuthClient(): + __public_key=None @staticmethod def _get_keycloak_user_id(): @@ -74,12 +74,12 @@ def __init__(self): Init the class and checks the connectivity to the KeyCloak server """ # test if we can connect to the Keycloak server - dummy_client = self.get_admin_client() + dummy_client = self.get_admin_client() def get_admin_client(self): """ Setup and return a keycloak admin client - + The client will connect to the Keycloak server with the default admin credentials and connects to the 'master' realm. The client uses the application realm for read/write to the Keycloak server @@ -94,15 +94,27 @@ def get_admin_client(self): realm_name=AUTH_REALM, user_realm_name='master', verify=True) - try: - # test if the connection still is authenticated, if not refresh the token - dummy = self._admin_client.get_realms() - except KeycloakAuthenticationError: - self._admin_client.refresh_token() return self._admin_client - @staticmethod - def decode_token(token): + def refresh_token(self): + try: + self._admin_client.refresh_token() + except Exception as e: + # reset the internal admin client to create a new one + self._admin_client = None + self.get_admin_client() + + @classmethod + def get_public_key(cls): + if not cls.__public_key: + AUTH_PUBLIC_KEY_URL = os.path.join(SERVER_URL, "realms", AUTH_REALM) + + KEY = json.loads(requests.get(AUTH_PUBLIC_KEY_URL, verify=False).text)['public_key'] + cls.__public_key = b"-----BEGIN PUBLIC KEY-----\n" + str.encode(KEY) + b"\n-----END PUBLIC KEY-----" + return cls.__public_key + + @classmethod + def decode_token(cls, token): """ Check and retrieve authentication information from custom bearer token. Returned value will be passed in 'token_info' parameter of your operation function, if there is one. @@ -113,14 +125,12 @@ def decode_token(token): :return: Decoded token information or None if token is invalid :rtype: dict | None """ - AUTH_PUBLIC_KEY_URL = f'{SERVER_URL}realms/{AUTH_REALM}' - KEY = json.loads(requests.get(AUTH_PUBLIC_KEY_URL, verify=False).text)['public_key'] - KEY = b"-----BEGIN PUBLIC KEY-----\n" + str.encode(KEY) + b"\n-----END PUBLIC KEY-----" - decoded = jwt.decode(token, KEY, algorithms='RS256', audience='account') + decoded = jwt.decode(token, cls.get_public_key(), algorithms='RS256', audience='account') return decoded + @with_refreshtoken def get_client(self, client_name): """ Return the KC client @@ -132,13 +142,11 @@ def get_client(self, client_name): :return: ClientRepresentation or False when not found """ admin_client = self.get_admin_client() - try: - client_id = admin_client.get_client_id(client_name) - client = admin_client.get_client(client_id) - except: - return False + client_id = admin_client.get_client_id(client_name) + client = admin_client.get_client(client_id) return client + @with_refreshtoken def create_client(self, client_name, protocol="openid-connect", @@ -162,7 +170,7 @@ def create_client(self, :return: True on success or exception """ admin_client = self.get_admin_client() - admin_client.create_client({ + x= admin_client.create_client({ 'id': client_name, 'name': client_name, 'protocol': protocol, @@ -175,6 +183,7 @@ def create_client(self, }) return True + @with_refreshtoken def create_client_role(self, client_id, role): """ Creates a new client role if not exists @@ -184,18 +193,16 @@ def create_client_role(self, client_id, role): :return: True on success, False on error """ admin_client = self.get_admin_client() - try: - admin_client.create_client_role( - client_id, - { - 'name': role, - 'clientRole': True - } - ) - except: - return False + admin_client.create_client_role( + client_id, + { + 'name': role, + 'clientRole': True + } + ) return True + @with_refreshtoken def get_group(self, group_id, with_members=False): """ Return the group in the application realm @@ -210,9 +217,13 @@ def get_group(self, group_id, with_members=False): group = admin_client.get_group(group_id) if with_members: members = admin_client.get_group_members(group_id) + for user in members: + user.update({'userGroups': admin_client.get_user_groups(user['id'])}) + user.update({'realmRoles': admin_client.get_realm_roles_of_user(user['id'])}) group.update({'members': members}) return group + @with_refreshtoken def get_groups(self, with_members=False): """ Return a list of all groups in the application realm @@ -229,7 +240,8 @@ def get_groups(self, with_members=False): groups.append(self.get_group(group['id'], with_members)) return groups - def get_users(self): + @with_refreshtoken + def get_users(self, query=None): """ Return a list of all users in the application realm @@ -239,15 +251,18 @@ def get_users(self): GroupRepresentation https://www.keycloak.org/docs-api/8.0/rest-api/index.html#_grouprepresentation + :param query: query filtering the users see https://www.keycloak.org/docs-api/8.0/rest-api/index.html#_users_resource :return: List(UserRepresentation + GroupRepresentation) """ admin_client = self.get_admin_client() users = [] - for user in admin_client.get_users(): + for user in admin_client.get_users(query=query): user.update({'userGroups': admin_client.get_user_groups(user['id'])}) + user.update({'realmRoles': admin_client.get_realm_roles_of_user(user['id'])}) users.append(user) return users + @with_refreshtoken def get_user(self, user_id): """ Get the user including the user groups @@ -265,8 +280,24 @@ def get_user(self, user_id): admin_client = self.get_admin_client() user = admin_client.get_user(user_id) user.update({'userGroups': admin_client.get_user_groups(user_id)}) + user.update({'realmRoles': admin_client.get_realm_roles_of_user(user_id)}) return user + @with_refreshtoken + def get_user_realm_roles(self, user_id): + """ + Get the user including the user roles within the current realm + + :param user_id: User id + + RoleRepresentation + https://www.keycloak.org/docs-api/8.0/rest-api/index.html#_rolerepresentation + + :return: (array RoleRepresentation) + """ + admin_client = self.get_admin_client() + return admin_client.get_realm_roles_of_user(user_id) + def get_current_user(self): """ Get the current user including the user groups @@ -281,6 +312,20 @@ def get_current_user(self): """ return self.get_user(self._get_keycloak_user_id()) + def get_current_user_realm_roles(self): + """ + Get the user including the user roles within the current realm + + :param user_id: User id + + RoleRepresentation + https://www.keycloak.org/docs-api/8.0/rest-api/index.html#_rolerepresentation + + :return: (array RoleRepresentation) + """ + return self.get_user_realm_roles(self._get_keycloak_user_id()) + + @with_refreshtoken def get_user_client_roles(self, user_id, client_name): """ Get the user including the user resource access @@ -315,6 +360,17 @@ def user_has_client_role(self, user_id, client_name, role): roles = [user_client_role for user_client_role in self.get_user_client_roles(user_id, client_name) if user_client_role['name'] == role] return roles != [] + def user_has_realm_role(self, user_id, role): + """ + Tests if the user has the given role within the current realm + + :param user_id: User id + :param role: Name of the role + :return: (array RoleRepresentation) + """ + roles = [user_realm_role for user_realm_role in self.get_user_realm_roles(user_id) if user_realm_role['name'] == role] + return roles != [] + def current_user_has_client_role(self, client_name, role): """ Tests if the current user has the given role within the given client @@ -328,6 +384,18 @@ def current_user_has_client_role(self, client_name, role): client_name, role) + def current_user_has_realm_role(self, role): + """ + Tests if the current user has the given role within the current realm + + :param role: Name of the role + :return: (array RoleRepresentation) + """ + return self.user_has_realm_role( + self._get_keycloak_user_id(), + role) + + @with_refreshtoken def get_client_role_members(self, client_name, role): """ Get all users for the specified client and role @@ -340,6 +408,7 @@ def get_client_role_members(self, client_name, role): client_id = admin_client.get_client_id(client_name) return admin_client.get_client_role_members(client_id, role) + @with_refreshtoken def user_add_update_attribute(self, user_id, attribute_name, attribute_value): """ Adds or when exists updates the attribute to/of the User with the attribute value @@ -360,6 +429,7 @@ def user_add_update_attribute(self, user_id, attribute_name, attribute_value): }) return True + @with_refreshtoken def user_delete_attribute(self, user_id, attribute_name): """ Deletes the attribute to/of the User with the attribute value diff --git a/libraries/cloudharness-common/cloudharness/events/client.py b/libraries/cloudharness-common/cloudharness/events/client.py index 6bf05b99..fd30a5aa 100644 --- a/libraries/cloudharness-common/cloudharness/events/client.py +++ b/libraries/cloudharness-common/cloudharness/events/client.py @@ -41,15 +41,14 @@ def create_topic(self): client_id=self.client_id) # ## Create topic - topic_list = [NewTopic(name=self.topic_id, num_partitions=1, replication_factor=1)] - + new_topic = NewTopic(name=self.topic_id, num_partitions=1, replication_factor=1) try: - return admin_client.create_topics(new_topics=topic_list, validate_only=False) + return admin_client.create_topics(new_topics=[new_topic], validate_only=False) except TopicAlreadyExistsError as e: - log.error(f"Topic {self.topic_id} already exists.") - raise EventTopicCreationException from e + # topic already exists "no worries", proceed + return True except Exception as e: - log.error(f"Ups... We had an error creating the new Topic --> {e}") + log.error(f"Ups... We had an error creating the new Topics --> {e}", exc_info=True) raise EventGeneralException from e def produce(self, message: dict): @@ -64,22 +63,23 @@ def produce(self, message: dict): try: return producer.send(self.topic_id, value=message) except KafkaTimeoutError as e: - log.error("Ups... Not able to fetch topic metadata") + log.error("Ups... Not able to fetch topic metadata", exc_info=True) raise EventTopicProduceException from e except Exception as e: - raise EventGeneralException(f"Ups... We had an error creating the new Topic --> {e}") from e + log.error(f"Ups... We had an error produce to topic {self.topic_id} --> {e}", exc_info=True) + raise EventGeneralException from e finally: producer.close() def consume_all(self, group_id='default') -> list: ''' Return a list of messages published in the topic ''' - consumer = _get_consumer(group_id) + consumer = self._get_consumer(group_id) try: for topic in consumer.poll(10000).values(): return [record.value for record in topic] except Exception as e: - log.error(f"Ups... We had an error trying to create a CloudHarnessEvents consumer for topic {self.topic_id} --> {e}") + log.error(f"Ups... We had an error trying to consume all from topic {self.topic_id} --> {e}", exc_info=True) raise EventTopicConsumeException from e finally: consumer.close() @@ -99,31 +99,31 @@ def delete_topic(self) -> bool: raise EventTopicDeleteException from e except Exception as e: - log.error(f"Ups... We had an error deleteing the Topic {self.topic_id} --> {e}") + log.error(f"Ups... We had an error deleting the Topic {self.topic_id} --> {e}", exc_info=True) raise EventGeneralException from e def close(self): - if getattr(self, '_consumer_thread'): - self._consumer_thread.cancel() + if hasattr(self, '_consumer_thread'): + # for now no cleanup tasks to do + pass def _consume_task(self, app=None, group_id=None, handler=None): log.info(f'Kafka consumer thread started, listening for messages in queue: {self.topic_id}') while True: try: - consumer = self._get_consumer(group_id) - for message in consumer: + self.consumer = self._get_consumer(group_id) + for message in self.consumer: try: - handler(app, message.value) + handler(event_client=self, app=app, message=message.value) except Exception as e: - log.error(f"Ups... there was an error during execution of the consumer Topc {self.topic_id} --> {e}") + log.error(f"Ups... there was an error during execution of the consumer Topic {self.topic_id} --> {e}", exc_info=True) log.error(traceback.print_exc()) - consumer.close() + self.consumer.close() except Exception as e: - log.error(f"Ups... there was an error during execution of the consumer Topc {self.topic_id} --> {e}") + log.error(f"Ups... there was an error during execution of the consumer Topic {self.topic_id} --> {e}", exc_info=True) log.error(traceback.print_exc()) time.sleep(10) - - log.info(f'Kafka consumer thread {self.topic_id} stopped') + # log.info(f'Kafka consumer thread {self.topic_id} stopped') def async_consume(self, app=None, handler=None, group_id='default'): log.debug('creating thread') @@ -135,6 +135,7 @@ def async_consume(self, app=None, handler=None, group_id='default'): kwargs={'app': app, 'group_id': group_id, 'handler': handler}) + self._consumer_thread.daemon = True self._consumer_thread.start() log.debug('thread started') diff --git a/client/cloudharness_cli/test/samples/__init__.py b/libraries/cloudharness-common/cloudharness/infrastructure/__init__.py similarity index 100% rename from client/cloudharness_cli/test/samples/__init__.py rename to libraries/cloudharness-common/cloudharness/infrastructure/__init__.py diff --git a/libraries/cloudharness-common/cloudharness/infrastructure/k8s.py b/libraries/cloudharness-common/cloudharness/infrastructure/k8s.py new file mode 100644 index 00000000..41eff86b --- /dev/null +++ b/libraries/cloudharness-common/cloudharness/infrastructure/k8s.py @@ -0,0 +1,114 @@ +""" +Kubernetes base api. + +TODO: stubs for configuration and running queries are working, but not much functionality at the moment +""" +import kubernetes + +import yaml +import os +from pathlib import Path + +from cloudharness import log + +# TODO handle group + +version = 'v1alpha1' + +# determine the namespace of the current app and run the workflow in that namespace +from cloudharness.utils.config import CloudharnessConfig as conf + +namespace = conf.get_namespace() + + + + + + +# --- Api functions --- ` + +def get_api_client(): + configuration = get_configuration() + api_instance = kubernetes.client.CoreV1Api(kubernetes.client.ApiClient(get_configuration())) + return api_instance + + +def get_configuration(): + try: + configuration = kubernetes.config.load_incluster_config() + except: + log.warning('Kubernetes cluster configuration not found. Trying local configuration') + try: + configuration = kubernetes.config.load_kube_config() + except: + log.warning('Kubernetes local configuration not found. Using localhost proxy') + configuration = kubernetes.client.configuration.Configuration() + return configuration + + +api_instance = get_api_client() + + +def create_namespace(): + api_instance = kubernetes.client.CoreV1Api(kubernetes.client.ApiClient(get_configuration())) + body = kubernetes.client.V1Namespace(metadata=kubernetes.client.V1ObjectMeta(name=namespace)) # V1Namespace | + + + try: + api_response = api_instance.create_namespace(body) + except Exception as e: + raise Exception(f"Error creating namespace: {namespace}") from e + + + +def get_objects(group = 'argoproj.io', plural='workflows', status=None, limit=10, continue_token=None, timeout_seconds=3): + """https://github.com/kubernetes-client/python/blob/master/kubernetes/docs/CustomObjectsApi.md#list_namespaced_custom_object""" + # Notice: field selector doesn't work though advertised, except fot metadata.name and metadata.namespace https://github.com/kubernetes/kubernetes/issues/51046 + # The filtering by phase can be obtained through labels: https://github.com/argoproj/argo/issues/496 + + params = dict(pretty=False, timeout_seconds=timeout_seconds) + + api_response = api_instance.list_namespaced_custom_object(group, version, namespace, plural, **params) + return api_response + + +def get_object(object_name): + configuration = get_configuration() + api_instance = kubernetes.client.CustomObjectsApi(kubernetes.client.ApiClient(configuration)) + return api_instance.get_namespaced_custom_object(group, version, namespace, plural, object_name) + +def get_pod_logs(pod_name, namespace=namespace): + + try: + return api_instance.read_namespaced_pod_log(name=pod_name, namespace=namespace, container="main") + except kubernetes.client.rest.ApiException as e: + if e.status == 400: + return f"Pod {pod_name} has not emitted logs yet..." + raise Exception(e.status) from e + +def get_pod(pod_name, namespace=namespace): + + try: + return api_instance.read_namespaced_pod(name=pod_name, namespace=namespace) + except kubernetes.client.rest.ApiException as e: + if 404 == e.status: + raise Exception(f"Pod {pod_name} not found") + raise Exception(e.status) from e + +def get_pods(namespace=namespace): + try: + return api_instance.list_namespaced_pod( namespace=namespace) + except kubernetes.client.rest.ApiException as e: + raise Exception("Error retrieving pods") from e + +def get_deployments(namespace=namespace): + api_instance = kubernetes.client.AppsV1Api(kubernetes.client.ApiClient(get_configuration())) + try: + return api_instance.list_namespaced_deployment( namespace=namespace) + except kubernetes.client.rest.ApiException as e: + raise Exception("Error retrieving deployments") from e + +if __name__ == '__main__': + from pprint import pprint + + pprint(get_objects()) \ No newline at end of file diff --git a/client/cloudharness_cli/test/workflows/__init__.py b/libraries/cloudharness-common/cloudharness/persistence/nosql_database/mongo.py similarity index 100% rename from client/cloudharness_cli/test/workflows/__init__.py rename to libraries/cloudharness-common/cloudharness/persistence/nosql_database/mongo.py diff --git a/libraries/cloudharness-common/cloudharness/sentry/__init__.py b/libraries/cloudharness-common/cloudharness/sentry/__init__.py index ead24fef..f4a455ee 100644 --- a/libraries/cloudharness-common/cloudharness/sentry/__init__.py +++ b/libraries/cloudharness-common/cloudharness/sentry/__init__.py @@ -1,8 +1,11 @@ import json +import os import requests from cloudharness.utils.env import get_common_service_cluster_address +sentry_environment = os.environ.get("DOMAIN", "Production") + def get_dsn(appname): """ Helper function for getting the Sentry DSN of the project of the application @@ -49,6 +52,7 @@ def init(appname): integrations = [] sentry_sdk.init( dsn=dsn, + environment=sentry_environment, integrations=[FlaskIntegration()] ) diff --git a/libraries/cloudharness-common/cloudharness/utils/config.py b/libraries/cloudharness-common/cloudharness/utils/config.py index 4ecc8dfd..ec2a076a 100644 --- a/libraries/cloudharness-common/cloudharness/utils/config.py +++ b/libraries/cloudharness-common/cloudharness/utils/config.py @@ -1,7 +1,8 @@ import yaml + import os -ALLVALUES_PATH = '/opt/cloudharness/resources/allvalues.yaml' +ALLVALUES_PATH = os.getenv("CH_VALUES_PATH", '/opt/cloudharness/resources/allvalues.yaml') class ConfigObject(object): @@ -29,7 +30,7 @@ class CloudharnessConfig: via the harness-deployment script """ - allvalues=None + allvalues={} @classmethod def _get_all_values(cls): @@ -44,6 +45,25 @@ def _get_apps(cls): cls.apps = ConfigObject(cls._get_all_values()['apps']) return cls.apps + @classmethod + def get_namespace(cls): + return cls.get_configuration()['namespace'] + + @classmethod + def get_domain(cls): + return cls.get_configuration()['domain'] + + @classmethod + def is_secured(cls): + try: + return bool(cls.get_configuration()['tls']) + except KeyError: + return False + + @classmethod + def is_test(cls): + return 'test' in cls.get_configuration() and cls.get_configuration()['test'] + @classmethod def get_application_by_filter(cls, **filter): """ diff --git a/libraries/cloudharness-common/cloudharness/utils/env.py b/libraries/cloudharness-common/cloudharness/utils/env.py index cfa089f0..4559d88f 100644 --- a/libraries/cloudharness-common/cloudharness/utils/env.py +++ b/libraries/cloudharness-common/cloudharness/utils/env.py @@ -22,10 +22,13 @@ def set_default_environment(): values = conf.get_configuration() - if values: + + if values and 'env' in values: os.environ.update({v['name']: str(v["value"]) for v in values['env'] if v['name'] not in os.environ}) + + set_default_environment() def get_namespace(): @@ -101,7 +104,7 @@ def get_cloudharness_events_service(): def get_service_cluster_address(cloudharness_app_name): if use_public_services(): return get_service_public_address(cloudharness_app_name) - return get_sub_variable(cloudharness_app_name, SUFFIX_NAME) + ':' + get_sub_variable(cloudharness_app_name, SUFFIX_PORT) + return cluster_service_address(cloudharness_app_name) def cluster_service_address(service_name): diff --git a/libraries/cloudharness-common/cloudharness/utils/server.py b/libraries/cloudharness-common/cloudharness/utils/server.py new file mode 100644 index 00000000..77425101 --- /dev/null +++ b/libraries/cloudharness-common/cloudharness/utils/server.py @@ -0,0 +1,91 @@ +import os +import inspect + +import flask +import connexion +from connexion.apps.flask_app import FlaskJSONEncoder +import six + +from cloudharness import log as logging + +app = None + +class JSONEncoder(FlaskJSONEncoder): + include_nulls = False + + def default(self, o): + if hasattr(o, 'openapi_types'): + dikt = {} + for attr, _ in six.iteritems(o.openapi_types): + value = getattr(o, attr) + if value is None and not self.include_nulls: + continue + attr = o.attribute_map[attr] + dikt[attr] = value + return dikt + return FlaskJSONEncoder.default(self, o) + + +def init_webapp_routes(app: flask.Flask, www_path): + + @app.route('/test', methods=['GET']) + def test(): + return 'routing ok' + + @app.route('/', methods=['GET']) + def index(): + return flask.send_from_directory(www_path, 'index.html') + + @app.route('/', methods=['GET']) + def send_webapp(path): + return flask.send_from_directory(www_path, path) + + + + @app.route('/static/', methods=['GET']) + def send_static(path): + return flask.send_from_directory(os.path.join(www_path, 'static'), path) + +class Config(object): + DEBUG = False + TESTING = False + CSRF_ENABLED = True + +def init_flask(title='CH service API', init_app_fn=None, webapp=False, json_encoder=JSONEncoder, resolver=None, config=Config): + """ + + """ + global app + + # Some magic inspection to get the caller's absolute path + import inspect, os + frm = inspect.stack()[1] + mod = inspect.getmodule(frm[0]) + caller_path = os.path.dirname(os.path.realpath(mod.__file__)) + + connexion_app = connexion.App(__name__) + app = connexion_app.app + obj_config = os.environ.get('APP_SETTINGS', config) + if obj_config: + app.config.from_object(obj_config) + app.json_encoder = json_encoder + + with app.app_context(): + # setup logging + gunicorn_logger = logging.getLogger("gunicorn.error") + app.logger.handlers = gunicorn_logger.handlers + app.logger.setLevel(gunicorn_logger.level) + + if webapp: + init_webapp_routes(app, www_path=os.path.join(os.path.dirname(caller_path), 'www')) + connexion_app.add_api(os.path.join(caller_path, 'openapi/openapi.yaml'), + arguments={'title': title}, + pythonic_params=True, resolver=resolver) + + if init_app_fn: + init_app_fn(app) + + return app + +def main(): + app.run( host='0.0.0.0', port=os.getenv('PORT', 5001)) \ No newline at end of file diff --git a/libraries/cloudharness-common/cloudharness/workflows/argo.py b/libraries/cloudharness-common/cloudharness/workflows/argo.py index 3550c8b7..3c977cb3 100644 --- a/libraries/cloudharness-common/cloudharness/workflows/argo.py +++ b/libraries/cloudharness-common/cloudharness/workflows/argo.py @@ -3,25 +3,18 @@ Reference: https://argoproj.github.io/docs/argo/docs/rest-api.html https://github.com/kubernetes-client/python/blob/master/kubernetes/docs/CustomObjectsApi.md """ -import kubernetes import yaml -import os -from pathlib import Path -from cloudharness import log - -group = 'argoproj.io' -version = 'v1alpha1' - -plural = 'workflows' +from argo.workflows.client import ApiClient, WorkflowServiceApi, Configuration, V1alpha1WorkflowCreateRequest, \ + V1alpha1Workflow # determine the namespace of the current app and run the workflow in that namespace from cloudharness.utils.config import CloudharnessConfig as conf -ch_conf = conf.get_configuration() -namespace = ch_conf and ch_conf.get('namespace','argo-workflows') +from cloudharness import log, applications -CUSTOM_OBJECT_URL = f"/apis/{group}/{version}/{plural}" +ch_conf = conf.get_configuration() +namespace = conf.get_namespace() class WorkflowException(Exception): @@ -67,11 +60,11 @@ def phases(cls): class Workflow: - def __init__(self, raw_dict): - self.name = raw_dict['metadata']['name'] - self.status = raw_dict['status']['phase'] if 'status' in raw_dict else None - self.create_time = raw_dict['metadata']['creationTimestamp'] - self.raw = raw_dict + def __init__(self, api_workflow: V1alpha1Workflow): + self.name = api_workflow.metadata.name + self.status = api_workflow.status.phase if api_workflow.status else None + self.create_time = api_workflow.metadata.creation_timestamp + self.raw = api_workflow def is_finished(self): return self.status in (Phase.NodeError, Phase.NodeSucceeded, Phase.NodeSkipped, Phase.NodeFailed) @@ -86,12 +79,17 @@ def failed(self): return self.status == Phase.NodeFailed def get_status_message(self): - return self.raw['status']['message'] + return self.raw.status.message + + @property + def pod_names(self): + return [node.id for node in self.raw.status.nodes.values() if not node.children] + class SearchResult: def __init__(self, raw_dict): - self.items = tuple(Workflow(item) for item in raw_dict['items']) - self.continue_token = raw_dict['metadata']['continue'] + self.items = tuple(Workflow(item) for item in raw_dict.items) + self.continue_token = raw_dict.metadata._continue self.raw = raw_dict def __str__(self): @@ -107,56 +105,16 @@ def get_api_client(): configuration = get_configuration() # configuration.api_key['authorization'] = 'YOUR_API_KEY' # TODO verify if we need an api key - api_instance = kubernetes.client.CustomObjectsApi(kubernetes.client.ApiClient(configuration)) + api_instance = ApiClient(configuration) return api_instance def get_configuration(): - try: - configuration = kubernetes.config.load_incluster_config() - - except: - log.warning('Kubernetes cluster configuration not found. Trying local configuration') - - try: - configuration = kubernetes.config.load_kube_config( - config_file=os.path.join(str(Path.home()), '.kube', 'config')) - except: - log.warning('Kubernetes local configuration not found. Using localhost proxy') - configuration = kubernetes.client.configuration.Configuration() - host = 'http://localhost:8001' - configuration.host = host - return configuration - - -api_instance = get_api_client() - -def check_namespace(): - api_instance = kubernetes.client.CoreV1Api(kubernetes.client.ApiClient(get_configuration())) - try: - api_response = api_instance.read_namespace(namespace, exact=True) - except kubernetes.client.rest.ApiException as e: - - raise Exception("Namespace for argo workflows does not exist:" + namespace) from e - -def create_namespace(): - api_instance = kubernetes.client.CoreV1Api(kubernetes.client.ApiClient(get_configuration())) - body = kubernetes.client.V1Namespace(metadata=kubernetes.client.V1ObjectMeta(name=namespace)) # V1Namespace | - - - try: - api_response = api_instance.create_namespace(body) - except Exception as e: - raise Exception("Error creating namespace:" + namespace) from e -try: - check_namespace() -except Exception as e: - log.error('Namespace for argo workflows not found', exc_info=e) - log.info("Creating namespace %s", namespace) - try: - create_namespace() - except Exception as e: - log.error('Cannot connect with argo', exc_info=e) + if not conf.is_test(): + host = applications.get_configuration('argo').get_service_address() + else: + host = applications.get_configuration('argo').get_public_address() + return Configuration(host=host) def get_workflows(status=None, limit=10, continue_token=None, timeout_seconds=3) -> SearchResult: @@ -164,27 +122,24 @@ def get_workflows(status=None, limit=10, continue_token=None, timeout_seconds=3) # Notice: field selector doesn't work though advertised, except fot metadata.name and metadata.namespace https://github.com/kubernetes/kubernetes/issues/51046 # The filtering by phase can be obtained through labels: https://github.com/argoproj/argo/issues/496 - params = dict(pretty=False, timeout_seconds=timeout_seconds) - if status is not None: - if (status not in Phase.phases()): - raise BadParam(status, 'Status must be one of {}'.format(Phase.phases())) - params['label_selector'] = f'workflows.argoproj.io/phase={status}' - api_response = api_instance.list_namespaced_custom_object(group, version, namespace, plural, **params) + service = WorkflowServiceApi(api_client=get_api_client()) - # TODO implement limit and continue, see https://github.com/kubernetes-client/python/issues/965 - # api_response = api_instance.list_cluster_custom_object(group, version, plural, pretty=False, timeout_seconds=timeout_seconds, watch=watch, limit=limit, continue_token=continue_token) + # pprint(service.list_workflows('ch', V1alpha1WorkflowList())) + api_response = service.list_workflows(namespace, list_options_limit=limit, list_options_continue=continue_token, + list_options_timeout_seconds=timeout_seconds) return SearchResult(api_response) def submit_workflow(spec) -> Workflow: - """https://github.com/kubernetes-client/python/blob/master/kubernetes/docs/CustomObjectsApi.md#create_namespaced_custom_object""" - log.debug(f"Submitting workflow\n{spec}") - workflow = Workflow( - api_instance.create_namespaced_custom_object(group, version, namespace, plural, spec, pretty=False)) - log.info(f"Submitted argo workflow {workflow.name}") - if workflow.failed(): - raise WorkflowException("Workflow failed: " + workflow.get_status_message()) - return workflow + log.debug(f"Submitting workflow %s", spec) + + service = WorkflowServiceApi(api_client=get_api_client()) + + req = V1alpha1WorkflowCreateRequest(workflow=spec, instance_id=namespace, namespace=namespace) + + # pprint(service.list_workflows('ch', V1alpha1WorkflowList())) + wf = service.create_workflow(namespace, req) + return Workflow(wf) def delete_workflow(workflow_name): @@ -199,37 +154,32 @@ def delete_workflow(workflow_name): def get_workflow(workflow_name) -> Workflow: + service = WorkflowServiceApi(api_client=get_api_client()) try: - workflow = Workflow(api_instance.get_namespaced_custom_object(group, version, namespace, plural, workflow_name)) - except kubernetes.client.rest.ApiException as e: + api_response = service.get_workflow(namespace, name=workflow_name) + except Exception as e: if e.status == 404: raise WorkflowNotFound() - raise WorkflowException(e.status) from e + raise WorkflowException("Workflow get error") from e + workflow = Workflow(api_response) if workflow.failed(): raise WorkflowException("Workflow failed: " + workflow.get_status_message()) + return workflow + def get_workflow_logs(workflow_name) -> str: - core_api_instance = kubernetes.client.CoreV1Api(kubernetes.client.ApiClient(get_configuration())) - - try: - wf = api_instance.get_namespaced_custom_object(group, version, namespace, plural, workflow_name) - except kubernetes.client.rest.ApiException as e: - if e.status == 404: - raise WorkflowNotFound() - raise WorkflowException(e.status) from e - - pod_names = [node['id'] for node in wf['status']['nodes'].values() if not 'children' in node] - + return '\n'.join(get_workflow_logs_list(workflow_name)) + + +def get_workflow_logs_list(workflow_name): + from ..infrastructure import k8s + + workflow = get_workflow(workflow_name) + pod_names = workflow.pod_names if len(pod_names) == 0: return '' - - try: - return core_api_instance.read_namespaced_pod_log(name=pod_names[0], namespace=namespace, container="main") - except kubernetes.client.rest.ApiException as e: - if e.status == 400: - return "This step has not emitted logs yet..." - raise WorkflowException(e.status) from e + return [k8s.get_pod_logs(pod_name) for pod_name in pod_names] if __name__ == '__main__': diff --git a/libraries/cloudharness-common/cloudharness/workflows/operations.py b/libraries/cloudharness-common/cloudharness/workflows/operations.py index 79760082..78260e2a 100644 --- a/libraries/cloudharness-common/cloudharness/workflows/operations.py +++ b/libraries/cloudharness-common/cloudharness/workflows/operations.py @@ -1,21 +1,20 @@ -from collections.abc import Iterable import time -import yaml, pyaml +import pyaml + +from collections.abc import Iterable -SERVICE_ACCOUNT = 'argo-workflows' from cloudharness_cli.workflows.models.operation_status import OperationStatus from cloudharness.events.client import EventClient from cloudharness.utils.settings import CODEFRESH_PULL_SECRET from cloudharness.utils import env +from cloudharness import log from . import argo - from .tasks import Task, SendResultTask, CustomTask -from cloudharness import log - POLLING_WAIT_SECONDS = 1 +SERVICE_ACCOUNT = 'argo-workflows' class BadOperationConfiguration(RuntimeError): @@ -58,28 +57,31 @@ def templates(self): raise NotImplemented def to_workflow(self, **arguments): - workflow = { + return { 'apiVersion': 'argoproj.io/v1alpha1', 'kind': 'Workflow', 'metadata': {'generateName': self.name}, 'spec': self.spec() - } - return workflow def spec(self): spec = { 'entrypoint': self.entrypoint, - 'TTLSecondsAfterFinished': 24*60*60, # remove the workflow & pod after 1 day + 'ttlStrategy': { + 'secondsAfterCompletion': 60 * 60, + 'secondsAfterSuccess': 60 * 20, + 'secondsAfterFailure': 60 * 120, + }, 'templates': [self.modify_template(template) for template in self.templates], 'serviceAccountName': SERVICE_ACCOUNT, 'imagePullSecrets': [{'name': CODEFRESH_PULL_SECRET}], 'volumes': [{ - 'name': 'cloudharness-allvalues', + # mount allvalues so we can use the cloudharness Python library + 'name': 'cloudharness-allvalues', 'configMap': { 'name': 'cloudharness-allvalues' } - }] # mount allvalues so we can use the cloudharness Python library + }] } if self.on_exit_notify: spec = self.add_on_exit_notify_handler(spec) @@ -110,11 +112,9 @@ def submit(self): op = self.to_workflow() log.debug("Submitting workflow\n" + pyaml.dump(op)) - log.error(pyaml.dump(op)) - print(pyaml.dump(op)) - - self.persisted = argo.submit_workflow(op) # TODO use rest api for that? Include this into cloudharness.workflows? + # TODO use rest api for that? Include this into cloudharness.workflows? + self.persisted = argo.submit_workflow(op) return self.persisted def is_running(self): @@ -258,8 +258,10 @@ def templates(self): def spec(self): spec = super().spec() if self.volumes: - spec['volumeClaimTemplates'] = [self.spec_volumeclaim(volume) for volume in self.volumes if ':' not in volume] # without PVC prefix (e.g. /location) - spec['volumes'] += [self.spec_volume(volume) for volume in self.volumes if ':' in volume] # with PVC prefix (e.g. pvc-001:/location) + spec['volumeClaimTemplates'] = [self.spec_volumeclaim(volume) for volume in self.volumes if + ':' not in volume] # without PVC prefix (e.g. /location) + spec['volumes'] += [self.spec_volume(volume) for volume in self.volumes if + ':' in volume] # with PVC prefix (e.g. pvc-001:/location) return spec def modify_template(self, template): @@ -272,7 +274,7 @@ def volume_template(self, volume): path = volume if ":" in path: path = volume.split(':')[-1] - return dict({'name': self.name_from_path(path), 'mountPath': path }) + return dict({'name': self.name_from_path(path), 'mountPath': path}) def spec_volumeclaim(self, volume): # when the volume is NOT prefixed by a PVC (e.g. /location) then create a temporary PVC for the workflow @@ -305,6 +307,7 @@ def spec_volume(self, volume): } return {} + class PipelineOperation(CompositeOperation): def steps_spec(self): @@ -334,12 +337,12 @@ def execute(self, timeout=None): result = self.client.consume_all() if result is None: - raise RuntimeError("Operation `" + op.name + "` did not put results in the queue. Check your workflow configuration") + raise RuntimeError( + "Operation `" + op.name + "` did not put results in the queue. Check your workflow configuration") self.client.delete_topic() return result - class ParallelOperation(CompositeOperation): def steps_spec(self): diff --git a/libraries/cloudharness-common/cloudharness/workflows/tasks.py b/libraries/cloudharness-common/cloudharness/workflows/tasks.py index 6c11a220..db7a9d6c 100644 --- a/libraries/cloudharness-common/cloudharness/workflows/tasks.py +++ b/libraries/cloudharness-common/cloudharness/workflows/tasks.py @@ -1,13 +1,11 @@ from . import argo -import time -SERVICE_ACCOUNT = 'argo-workflows' - -from cloudharness import log from cloudharness.utils.env import get_cloudharness_variables, get_image_full_tag - from .utils import WORKFLOW_NAME_VARIABLE_NAME +SERVICE_ACCOUNT = 'argo-workflows' + + class Task(argo.ArgoObject): """ Abstract interface for a task. @@ -64,10 +62,10 @@ def spec(self): 'resources': self.resources, 'imagePullPolicy': self.image_pull_policy, 'volumeMounts': [{ - 'name': 'cloudharness-allvalues', - 'mountPath': '/opt/cloudharness/resources/allvalues.yaml', - 'subPath': 'allvalues.yaml' - }], + 'name': 'cloudharness-allvalues', + 'mountPath': '/opt/cloudharness/resources/allvalues.yaml', + 'subPath': 'allvalues.yaml' + }], }, 'inputs': {}, 'metadata': {}, diff --git a/libraries/cloudharness-common/cloudharness/workflows/utils.py b/libraries/cloudharness-common/cloudharness/workflows/utils.py index fcea0ba8..ac2ea3ec 100644 --- a/libraries/cloudharness-common/cloudharness/workflows/utils.py +++ b/libraries/cloudharness-common/cloudharness/workflows/utils.py @@ -5,18 +5,20 @@ WORKFLOW_NAME_VARIABLE_NAME = "CH_WORKFLOW_NAME" - SHARED_DIRECTORY_VARIABLE_NAME = "shared_directory" + def get_workflow_name(): """Get the workflow name from inside a workflow""" name = get_variable(WORKFLOW_NAME_VARIABLE_NAME) remove = name.split("-")[-1] - return name[0:-len(remove)-1] + return name[0:-len(remove) - 1] + def get_shared_directory(): return os.getenv(SHARED_DIRECTORY_VARIABLE_NAME) + def notify_queue(queue, message): client = EventClient(queue) client.produce(message) diff --git a/libraries/cloudharness-common/requirements.txt b/libraries/cloudharness-common/requirements.txt index d50d5d79..b92de7bd 100644 --- a/libraries/cloudharness-common/requirements.txt +++ b/libraries/cloudharness-common/requirements.txt @@ -2,11 +2,8 @@ asn1crypto==0.24.0 certifi==2019.3.9 cffi==1.12.2 chardet==3.0.4 -cryptography==3.2 idna==2.8 -jwt==1.0.0 -pycosat==0.6.3 -pycparser==2.19 +pyjwt>=1.7.1,<2 pyOpenSSL==19.0.0 PySocks==1.6.8 requests==2.21.0 @@ -19,3 +16,4 @@ kafka-python kubernetes sentry-sdk[flask]==0.14.4 python-keycloak==0.23.0 +argo-workflows==5.0.0 diff --git a/libraries/cloudharness-common/setup.py b/libraries/cloudharness-common/setup.py index 931fcde9..c8b94a7b 100644 --- a/libraries/cloudharness-common/setup.py +++ b/libraries/cloudharness-common/setup.py @@ -3,7 +3,7 @@ NAME = "cloudharness" -VERSION = "0.2.0" +VERSION = "0.3.0" # To install the library, run the following # # python setup.py install @@ -15,10 +15,12 @@ 'kubernetes', 'kafka-python', 'pyaml', - 'jwt', + 'pyjwt>=1.7.1,<2', + 'cryptography', 'requests>=2.21.0', 'sentry-sdk[flask]>=0.14.4', - 'python-keycloak==0.23.0' + 'python-keycloak==0.23.0', + 'argo-workflows' ] diff --git a/libraries/cloudharness-common/test-requirements.txt b/libraries/cloudharness-common/test-requirements.txt index 1ec5c478..435a3ac4 100644 --- a/libraries/cloudharness-common/test-requirements.txt +++ b/libraries/cloudharness-common/test-requirements.txt @@ -5,3 +5,5 @@ py>=1.4.31 randomize>=0.13 pytest>=5.0.0 pytest-cov +-e . +-e ../client/cloudharness_cli \ No newline at end of file diff --git a/libraries/cloudharness-common/tests/test_applications.py b/libraries/cloudharness-common/tests/test_applications.py index 01f0b32b..dff50002 100644 --- a/libraries/cloudharness-common/tests/test_applications.py +++ b/libraries/cloudharness-common/tests/test_applications.py @@ -1,8 +1,9 @@ from cloudharness.applications import ApplicationConfiguration, get_configuration conf_1 = { - 'name': 'app1', + 'harness': { + 'name': 'app1', 'service': { 'auto': False }, @@ -14,8 +15,9 @@ } conf_2 = { - 'name': 'app2', + 'harness': { + 'name': 'app2', 'service': { 'auto': False }, @@ -27,8 +29,9 @@ } conf_2sub = { - 'name': 'app2sub', + 'harness': { + 'name': 'app2sub', 'service': { 'auto': True }, @@ -70,7 +73,6 @@ def test_get_configuration(): assert not uut.is_auto_deployment() assert uut.is_sentry_enabled() - # uut = get_configuration('app2sub') # FIXME this should work uut = uut.subapp diff --git a/libraries/cloudharness-common/tests/test_env.py b/libraries/cloudharness-common/tests/test_env.py index adcd7dc7..77bd2768 100644 --- a/libraries/cloudharness-common/tests/test_env.py +++ b/libraries/cloudharness-common/tests/test_env.py @@ -1,31 +1,14 @@ import pytest +import os import yaml from cloudharness.utils.env import * +from cloudharness.utils.config import CloudharnessConfig as conf +HERE = os.path.dirname(os.path.realpath(__file__)).replace(os.path.sep, '/') +def set_test_environment(): + with open(os.path.join(HERE, 'values.yaml')) as f: + values = yaml.safe_load(f) + conf.get_configuration().update(values) + set_default_environment() - - - -def test_variables(): - os.environ['CH_USE_PUBLIC'] = "False" - assert 'CH_DOMAIN' in os.environ - - assert get_variable('CH_DOMAIN') == 'cloudharness.metacell.us' - assert get_sub_variable('CH_DOCS', 'NAME') == 'ch-docs' - assert get_sub_variable('CH-docs', 'NAME') == 'ch-docs' - assert get_sub_variable('CH_DOCS', 'IMAGE_NAME') == 'ch-docs' - - assert get_sub_variable('CH_DOCS', 'PORT') == '8080' - - assert get_image_registry() == 'localhost:5000' - assert get_auth_service_url() == 'accounts.cloudharness.metacell.us' - assert get_auth_service_cluster_address() == 'keycloak:8080' - assert get_cloudharness_events_client_id() == 'web-client' - assert get_cloudharness_workflows_service_url() == 'workflows.cloudharness.metacell.us' - assert get_image_full_tag('workflows-extract-download') == 'localhost:5000/workflows-extract-download:latest' - - with pytest.raises(VariableNotFound) as raised: - get_variable('CH_FAKE') - - assert raised.value.variable_name == 'CH_FAKE' diff --git a/libraries/cloudharness-common/tests/test_infrastructure.py b/libraries/cloudharness-common/tests/test_infrastructure.py new file mode 100644 index 00000000..c9395467 --- /dev/null +++ b/libraries/cloudharness-common/tests/test_infrastructure.py @@ -0,0 +1,13 @@ +from .test_env import set_test_environment + +set_test_environment() + +from cloudharness.infrastructure import k8s + +kubectl_enabled = False + + +def test_get_pods(): + if not kubectl_enabled: + return + return k8s.get_pods(namespace='kube_system') diff --git a/libraries/cloudharness-common/tests/test_integration.py b/libraries/cloudharness-common/tests/test_integration.py index 5139c625..9da8a087 100644 --- a/libraries/cloudharness-common/tests/test_integration.py +++ b/libraries/cloudharness-common/tests/test_integration.py @@ -1,2 +1,2 @@ def test_something(): - assert True \ No newline at end of file + assert True diff --git a/libraries/cloudharness-common/tests/test_workflow.py b/libraries/cloudharness-common/tests/test_workflow.py index 8a8e09ca..3cb15144 100644 --- a/libraries/cloudharness-common/tests/test_workflow.py +++ b/libraries/cloudharness-common/tests/test_workflow.py @@ -1,15 +1,18 @@ """Notice, this test needs a fully operating kubernetes with argo environment in the container running the test""" -import time +import requests +import yaml + +from .test_env import set_test_environment + +set_test_environment() -from cloudharness.workflows import operations +from cloudharness.workflows import operations, tasks from cloudharness import set_debug +from cloudharness.workflows import argo set_debug() -import yaml -from .test_env import set_default_environment - -set_default_environment() +execute = False def test_sync_workflow(): @@ -18,11 +21,12 @@ def f(): time.sleep(2) print('whatever') - task = operations.PythonTask('my-task', f) + task = tasks.PythonTask('my-task', f) op = operations.DistributedSyncOperation('test-sync-op-', task) print('\n', yaml.dump(op.to_workflow())) - print(op.execute()) + if execute: + print(op.execute()) def test_pipeline_workflow(): @@ -31,9 +35,10 @@ def f(): time.sleep(2) print('whatever') - op = operations.PipelineOperation('test-pipeline-op-', (operations.PythonTask('step1', f), operations.PythonTask('step2', f))) + op = operations.PipelineOperation('test-pipeline-op-', (tasks.PythonTask('step1', f), tasks.PythonTask('step2', f))) print('\n', yaml.dump(op.to_workflow())) - print(op.execute()) + if execute: + print(op.execute()) def test_parallel_workflow(): @@ -42,9 +47,10 @@ def f(): time.sleep(2) print('whatever') - op = operations.ParallelOperation('test-parallel-op-', (operations.PythonTask('p1', f), operations.PythonTask('p2', f))) + op = operations.ParallelOperation('test-parallel-op-', (tasks.PythonTask('p1', f), tasks.PythonTask('p2', f))) print('\n', yaml.dump(op.to_workflow())) - print(op.execute()) + if execute: + print(op.execute()) def test_simpledag_workflow(): @@ -54,38 +60,89 @@ def f(): print('whatever') # p3 runs after p1 and p2 finish - op = operations.SimpleDagOperation('test-dag-op-', (operations.PythonTask('p1', f), operations.PythonTask('p2', f)), - operations.PythonTask('p3', f)) + op = operations.SimpleDagOperation('test-dag-op-', (tasks.PythonTask('p1', f), tasks.PythonTask('p2', f)), + tasks.PythonTask('p3', f)) print('\n', yaml.dump(op.to_workflow())) - print(op.execute()) + if execute: + print(op.execute()) + def test_custom_task_workflow(): - task = operations.CustomTask('download-file', 'cloudharness-workflows-extract-download', url='https://www.bing.com') - op = operations.PipelineOperation('test-custom-op-', (task, )) + task = operations.CustomTask('download-file', 'workflows-extract-download', url='https://www.bing.com') + op = operations.PipelineOperation('test-custom-op-', (task,)) print('\n', yaml.dump(op.to_workflow())) - print(op.execute()) + if execute: + print(op.execute()) def test_custom_connected_task_workflow(): shared_directory = '/mnt/shared' - task_write = operations.CustomTask('download-file', 'cloudharness-workflows-extract-download', url='https://raw.githubusercontent.com/openworm/org.geppetto/master/README.md') - task_print = operations.CustomTask('print-file', 'cloudharness-workflows-print-file', file_path=shared_directory + '/README.md') - op = operations.PipelineOperation('test-custom-connected-op-', (task_write, task_print), shared_directory=shared_directory) + task_write = operations.CustomTask('download-file', 'workflows-extract-download', + shared_directory=shared_directory, + url='https://raw.githubusercontent.com/openworm/org.geppetto/master/README.md') + task_print = operations.CustomTask('print-file', 'workflows-print-file', shared_directory=shared_directory, + file_path=shared_directory + '/README.md') + op = operations.PipelineOperation('test-custom-connected-op-', (task_write, task_print), + shared_directory=shared_directory, shared_volume_size=100) # op.execute() print('\n', yaml.dump(op.to_workflow())) - print(op.execute()) + if execute: + print(op.execute()) def test_result_task_workflow(): - task_write = operations.CustomTask('download-file', 'cloudharness-workflows-extract-download', url='https://raw.githubusercontent.com/openworm/org.geppetto/master/README.md') + task_write = operations.CustomTask('download-file', 'workflows-extract-download', + url='https://raw.githubusercontent.com/openworm/org.geppetto/master/README.md') op = operations.DistributedSyncOperationWithResults('test-sync-results-', task_write) - # op.execute() print('\n', yaml.dump(op.to_workflow())) - print(op.execute()) - - - -# op = operations.ParallelOperation('my_op', [task, operations.CustomTask('my-coreg', 'coregistration-init')]) + if execute: + print(op.execute()) + + +def test_get_workflows(): + if execute: + assert len(argo.get_workflows()) + + +def test_submit_workflow(): + WORKFLOW = 'https://raw.githubusercontent.com/argoproj/argo/v2.12.2/examples/dag-diamond-steps.yaml' + + resp = requests.get(WORKFLOW) + manifest: dict = yaml.safe_load(resp.text) + if execute: + wf = argo.submit_workflow(manifest) + assert wf + assert wf.name + + +def test_get_workflow(): + if not execute: + return + WORKFLOW = 'https://raw.githubusercontent.com/argoproj/argo/v2.12.2/examples/dag-diamond-steps.yaml' + + resp = requests.get(WORKFLOW) + manifest: dict = yaml.safe_load(resp.text) + wf = argo.submit_workflow(manifest) + wf = argo.get_workflow(wf.name) + assert wf + assert wf.name + try: + argo.get_workflow('riuhfsdhsdfsfisdf') + assert 1 == 0 # not found raises exception + except: + pass + + +def test_get_workflow_logs(): + if not execute: + return + WORKFLOW = 'https://raw.githubusercontent.com/argoproj/argo/v2.12.2/examples/dag-diamond-steps.yaml' + + resp = requests.get(WORKFLOW) + manifest: dict = yaml.safe_load(resp.text) + wf = argo.submit_workflow(manifest) + logs = argo.get_workflow_logs(wf.name) + assert all(log for log in logs) diff --git a/libraries/cloudharness-common/tests/values.yaml b/libraries/cloudharness-common/tests/values.yaml new file mode 100644 index 00000000..655fd4e7 --- /dev/null +++ b/libraries/cloudharness-common/tests/values.yaml @@ -0,0 +1,1113 @@ +local: true +secured_gatekeepers: false +nameOverride: '' +fullnameOverride: '' +domain: cloudharness.metacell.us +namespace: ch +registry: + name: localhost:5000/ + secret: '' +tag: latest +apps: + volumemanager: + harness: + name: volumemanager + subdomain: volumemanager + domain: null + secured: false + uri_role_mapping: + - uri: /* + roles: + - administrator + deployment: + auto: true + replicas: 1 + image: localhost:5000/volumemanager:latest + name: volumemanager + port: 8080 + resources: &id001 + requests: + memory: 32Mi + cpu: 25m + limits: + memory: 500Mi + cpu: 500m + service: + auto: true + name: volumemanager + port: 8080 + database: + auto: false + name: volumemanager-db + type: null + size: 1Gi + user: mnp + pass: metacell + mongo: + image: mongo:latest + ports: + - name: http + port: 27017 + postgres: + image: postgres:latest + initialdb: cloudharness + ports: + - name: http + port: 5432 + neo4j: + image: neo4j:latest + memory: + size: 256M + pagecache: + size: 64M + heap: + initial: 64M + max: 128M + dbms_security_auth_enabled: 'false' + ports: + - name: http + port: 7474 + - name: bolt + port: 7687 + resources: + requests: + memory: 512Mi + cpu: 200m + limits: + memory: 2Gi + cpu: 1000m + sentry: true + image: localhost:5000/volumemanager:latest + name: volumemanager + port: 8080 + resources: *id001 + accounts: + harness: + name: accounts + subdomain: accounts + domain: null + secured: false + uri_role_mapping: + - uri: /* + roles: + - administrator + deployment: + auto: false + replicas: 1 + image: localhost:5000/accounts:latest + name: accounts + port: 8080 + resources: &id002 + requests: + memory: 32Mi + cpu: 25m + limits: + memory: 500Mi + cpu: 500m + service: + auto: true + name: accounts + port: 8080 + database: + auto: false + name: accounts-db + type: null + size: 1Gi + user: mnp + pass: metacell + mongo: + image: mongo:latest + ports: + - name: http + port: 27017 + postgres: + image: postgres:latest + initialdb: cloudharness + ports: + - name: http + port: 5432 + neo4j: + image: neo4j:latest + memory: + size: 256M + pagecache: + size: 64M + heap: + initial: 64M + max: 128M + dbms_security_auth_enabled: 'false' + ports: + - name: http + port: 7474 + - name: bolt + port: 7687 + resources: + requests: + memory: 512Mi + cpu: 200m + limits: + memory: 2Gi + cpu: 1000m + admin: + pass: metacell + user: admin + role: administrator + client: + id: rest-client + secret: 5678eb6e-9e2c-4ee5-bd54-34e7411339e8 + db: + image: postgres:10.4 + initialdb: auth_db + name: keycloak-postgress + pass: password + user: user + enabled: true + harvest: true + webclient: + id: web-client + secret: 452952ae-922c-4766-b912-7b106271e34b + name: accounts + port: 8080 + subdomain: accounts + gatekeeper: + image: accounts-keycloak-gatekeeper + image: localhost:5000/accounts:latest + resources: *id002 + samples: + harness: + name: samples + subdomain: samples + domain: null + secured: false + uri_role_mapping: + - uri: /* + roles: + - administrator + deployment: + auto: true + replicas: 1 + image: localhost:5000/samples:latest + name: samples + port: 8080 + resources: &id003 + requests: + memory: 32Mi + cpu: 25m + limits: + memory: 500Mi + cpu: 500m + service: + auto: true + name: samples + port: 8080 + database: + auto: false + name: samples-db + type: null + size: 1Gi + user: mnp + pass: metacell + mongo: + image: mongo:latest + ports: + - name: http + port: 27017 + postgres: + image: postgres:latest + initialdb: cloudharness + ports: + - name: http + port: 5432 + neo4j: + image: neo4j:latest + memory: + size: 256M + pagecache: + size: 64M + heap: + initial: 64M + max: 128M + dbms_security_auth_enabled: 'false' + ports: + - name: http + port: 7474 + - name: bolt + port: 7687 + resources: + requests: + memory: 512Mi + cpu: 200m + limits: + memory: 2Gi + cpu: 1000m + sentry: true + port: 80 + env: + - name: WORKERS + value: '3' + image: localhost:5000/samples:latest + name: samples + port: 8080 + resources: *id003 + events: + harness: + name: events + subdomain: events + domain: null + secured: true + uri_role_mapping: + - uri: /* + roles: + - administrator + deployment: + auto: false + replicas: 1 + image: localhost:5000/events:latest + name: events + port: 8081 + resources: &id004 + requests: + memory: 32Mi + cpu: 25m + limits: + memory: 500Mi + cpu: 500m + service: + auto: true + name: events + port: 80 + database: + auto: false + name: events-db + type: null + size: 1Gi + user: mnp + pass: metacell + mongo: + image: mongo:latest + ports: + - name: http + port: 27017 + postgres: + image: postgres:latest + initialdb: cloudharness + ports: + - name: http + port: 5432 + neo4j: + image: neo4j:latest + memory: + size: 256M + pagecache: + size: 64M + heap: + initial: 64M + max: 128M + dbms_security_auth_enabled: 'false' + ports: + - name: http + port: 7474 + - name: bolt + port: 7687 + resources: + requests: + memory: 512Mi + cpu: 200m + limits: + memory: 2Gi + cpu: 1000m + kafka: + name: bootstrap + port: 9092 + image: localhost:5000/events:latest + name: events + port: 8081 + resources: *id004 + common: + harness: + name: common + subdomain: common + domain: null + secured: false + uri_role_mapping: + - uri: /* + roles: + - administrator + deployment: + auto: true + replicas: 1 + image: localhost:5000/common:latest + name: common + port: 8080 + resources: &id005 + requests: + memory: 128Mi + cpu: 100m + limits: + memory: 256Mi + cpu: 200m + service: + auto: true + name: common + port: 8080 + database: + auto: false + name: common-db + type: null + size: 1Gi + user: mnp + pass: metacell + mongo: + image: mongo:latest + ports: + - name: http + port: 27017 + postgres: + image: postgres:latest + initialdb: cloudharness + ports: + - name: http + port: 5432 + neo4j: + image: neo4j:latest + memory: + size: 256M + pagecache: + size: 64M + heap: + initial: 64M + max: 128M + dbms_security_auth_enabled: 'false' + ports: + - name: http + port: 7474 + - name: bolt + port: 7687 + resources: + requests: + memory: 512Mi + cpu: 200m + limits: + memory: 2Gi + cpu: 1000m + image: localhost:5000/common:latest + name: common + port: 8080 + resources: *id005 + argo: + harness: + name: argo + subdomain: argo + domain: null + secured: true + uri_role_mapping: + - uri: /* + roles: + - administrator + deployment: + auto: false + replicas: 1 + image: localhost:5000/argo:latest + name: argo + port: 8081 + resources: &id006 + requests: + memory: 32Mi + cpu: 25m + limits: + memory: 500Mi + cpu: 500m + service: + auto: false + name: argo-server + port: 2746 + database: + auto: false + name: argo-db + type: null + size: 1Gi + user: mnp + pass: metacell + mongo: + image: mongo:latest + ports: + - name: http + port: 27017 + postgres: + image: postgres:latest + initialdb: cloudharness + ports: + - name: http + port: 5432 + neo4j: + image: neo4j:latest + memory: + size: 256M + pagecache: + size: 64M + heap: + initial: 64M + max: 128M + dbms_security_auth_enabled: 'false' + ports: + - name: http + port: 7474 + - name: bolt + port: 7687 + resources: + requests: + memory: 512Mi + cpu: 200m + limits: + memory: 2Gi + cpu: 1000m + serviceaccount: argo-workflows + image: localhost:5000/argo:latest + name: argo-server + port: 8081 + resources: *id006 + jupyterhub: + harness: + name: jupyterhub + subdomain: jupyterhub + domain: null + secured: false + uri_role_mapping: + - uri: /* + roles: + - administrator + deployment: + auto: false + replicas: 1 + image: localhost:5000/jupyterhub:latest + name: jupyterhub + port: 8081 + resources: &id007 + requests: + memory: 32Mi + cpu: 25m + limits: + memory: 500Mi + cpu: 500m + service: + auto: false + name: proxy-public + port: 80 + database: + auto: false + name: jupyterhub-db + type: null + size: 1Gi + user: mnp + pass: metacell + mongo: + image: mongo:latest + ports: + - name: http + port: 27017 + postgres: + image: postgres:latest + initialdb: cloudharness + ports: + - name: http + port: 5432 + neo4j: + image: neo4j:latest + memory: + size: 256M + pagecache: + size: 64M + heap: + initial: 64M + max: 128M + dbms_security_auth_enabled: 'false' + ports: + - name: http + port: 7474 + - name: bolt + port: 7687 + resources: + requests: + memory: 512Mi + cpu: 200m + limits: + memory: 2Gi + cpu: 1000m + custom: {} + hub: + allowNamedServers: true + namedServerLimitPerUser: 10 + service: + type: ClusterIP + annotations: {} + ports: + nodePort: null + loadBalancerIP: null + baseUrl: / + cookieSecret: null + publicURL: null + initContainers: [] + uid: 1000 + fsGid: 1000 + nodeSelector: {} + concurrentSpawnLimit: 64 + consecutiveFailureLimit: 5 + activeServerLimit: null + image: + pullSecrets: false + imagePullSecret: + enabled: false + livenessProbe: + enabled: false + readinessProbe: + enabled: false + deploymentStrategy: + type: Recreate + rollingUpdate: null + db: + type: sqlite-pvc + upgrade: null + pvc: + annotations: {} + selector: {} + accessModes: + - ReadWriteOnce + storage: 1Gi + subPath: null + storageClassName: null + url: null + password: null + labels: {} + annotations: + prometheus.io/scrape: 'true' + prometheus.io/path: /hub/metrics + extraConfig: + timing: | + c.Spawner.port = 8000 + c.Spawner.http_timeout = 300 + c.Spawner.start_timeout = 300 + c.JupyterHub.tornado_settings = { "headers": { }} + spawner: c.Spawner.args = ["--debug", "--port=8000"] + extraConfigMap: {} + extraEnv: {} + extraContainers: [] + extraVolumes: [] + extraVolumeMounts: [] + resources: + requests: + cpu: 200m + memory: 512Mi + services: {} + imagePullPolicy: IfNotPresent + pdb: + enabled: true + minAvailable: 1 + networkPolicy: + enabled: false + egress: + - to: + - ipBlock: + cidr: 0.0.0.0/0 + rbac: + enabled: true + proxy: + secretToken: b3fed077c7538cfc5e2a6469ddac7d43a18fc645789407b53e580b7342b968d8 + service: + type: LoadBalancer + labels: {} + annotations: {} + nodePorts: + http: null + https: null + loadBalancerIP: null + chp: + image: + name: jupyterhub/configurable-http-proxy + tag: 4.0.1 + pullPolicy: IfNotPresent + livenessProbe: + enabled: false + readinessProbe: + enabled: false + resources: + requests: + cpu: 200m + memory: 512Mi + nginx: + image: + name: quay.io/kubernetes-ingress-controller/nginx-ingress-controller + tag: 0.15.0 + pullPolicy: IfNotPresent + proxyBodySize: 64m + resources: {} + lego: + image: + name: jetstack/kube-lego + tag: 0.1.7 + pullPolicy: IfNotPresent + resources: {} + labels: {} + nodeSelector: {} + pdb: + enabled: true + minAvailable: 1 + https: + enabled: true + type: letsencrypt + letsencrypt: + contactEmail: '' + manual: + key: null + cert: null + secret: + name: '' + key: tls.key + crt: tls.crt + hosts: [] + networkPolicy: + enabled: false + egress: + - to: + - ipBlock: + cidr: 0.0.0.0/0 + auth: + type: tmp + whitelist: + users: null + admin: + access: true + users: null + dummy: + password: null + ldap: + dn: + search: {} + user: {} + user: {} + state: + enabled: false + cryptoKey: null + singleuser: + extraTolerations: [] + nodeSelector: {} + extraNodeAffinity: + required: [] + preferred: [] + extraPodAffinity: + required: [] + preferred: [] + extraPodAntiAffinity: + required: [] + preferred: [] + networkTools: + image: + name: jupyterhub/k8s-network-tools + tag: 0.9-b51ffeb + cloudMetadata: + enabled: false + ip: 169.254.169.254 + networkPolicy: + enabled: false + egress: + - to: + - ipBlock: + cidr: 0.0.0.0/0 + except: + - 169.254.169.254/32 + events: true + extraAnnotations: {} + extraLabels: {} + extraEnv: {} + lifecycleHooks: null + initContainers: [] + extraContainers: [] + uid: 1000 + fsGid: 100 + serviceAccountName: null + storage: + type: dynamic + capacity: 2Mi + dynamic: + pvcNameTemplate: jupyter-{userid} + volumeNameTemplate: jupyter-{userid} + homeMountPath: /home/workspace + extraLabels: {} + image: + name: jupyter/base-notebook + tag: hub-1.1.0 + pullPolicy: IfNotPresent + imagePullSecret: + enabled: false + startTimeout: 300 + cpu: + limit: null + guarantee: null + memory: + limit: null + guarantee: 0.5G + extraResource: + limits: {} + guarantees: {} + cmd: jupyterhub-singleuser + defaultUrl: null + scheduling: + userScheduler: + enabled: false + replicas: 1 + logLevel: 4 + image: + name: gcr.io/google_containers/kube-scheduler-amd64 + tag: v1.11.2 + nodeSelector: {} + pdb: + enabled: true + minAvailable: 1 + resources: + requests: + cpu: 50m + memory: 256Mi + podPriority: + enabled: false + userPlaceholder: + enabled: true + replicas: 0 + corePods: + nodeAffinity: + matchNodePurpose: prefer + userPods: + nodeAffinity: + matchNodePurpose: prefer + prePuller: + hook: + enabled: true + extraEnv: {} + image: + name: jupyterhub/k8s-image-awaiter + tag: 0.9-b51ffeb + continuous: + enabled: false + extraImages: {} + pause: + image: + name: gcr.io/google_containers/pause + tag: '3.0' + ingress: + enabled: false + annotations: {} + hosts: [] + pathSuffix: '' + tls: null + cull: + enabled: true + users: false + timeout: 600 + every: 60 + concurrency: 10 + maxAge: 0 + debug: + enabled: false + image: localhost:5000/jupyterhub:latest + name: jupyterhub + port: 8081 + resources: *id007 + mywebapp: + harness: + name: mywebapp + subdomain: mywebapp + domain: null + secured: false + uri_role_mapping: + - uri: /* + roles: + - administrator + deployment: + auto: true + replicas: 1 + image: localhost:5000/mywebapp:latest + name: mywebapp + port: 8080 + resources: &id008 + requests: + memory: 32Mi + cpu: 25m + limits: + memory: 500Mi + cpu: 500m + service: + auto: true + name: mywebapp + port: 8080 + database: + auto: true + name: mywebapp-mongo-db + type: mongo + size: 1Gi + user: mnp + pass: metacell + mongo: + image: mongo:latest + ports: + - name: http + port: 27017 + postgres: + image: postgres:latest + initialdb: cloudharness + ports: + - name: http + port: 5432 + neo4j: + image: neo4j:latest + memory: + size: 256M + pagecache: + size: 64M + heap: + initial: 64M + max: 128M + dbms_security_auth_enabled: 'false' + ports: + - name: http + port: 7474 + - name: bolt + port: 7687 + resources: + requests: + memory: 512Mi + cpu: 200m + limits: + memory: 2Gi + cpu: 1000m + port: 80 + image: localhost:5000/mywebapp:latest + name: mywebapp + port: 8080 + resources: *id008 + workflows: + harness: + name: workflows + subdomain: workflows + domain: null + secured: false + uri_role_mapping: + - uri: /* + roles: + - administrator + deployment: + auto: true + replicas: 1 + image: localhost:5000/workflows:latest + name: workflows + port: 8080 + resources: &id009 + requests: + memory: 32Mi + cpu: 25m + limits: + memory: 500Mi + cpu: 500m + service: + auto: true + name: workflows + port: 8080 + database: + auto: false + name: workflows-db + type: null + size: 1Gi + user: mnp + pass: metacell + mongo: + image: mongo:latest + ports: + - name: http + port: 27017 + postgres: + image: postgres:latest + initialdb: cloudharness + ports: + - name: http + port: 5432 + neo4j: + image: neo4j:latest + memory: + size: 256M + pagecache: + size: 64M + heap: + initial: 64M + max: 128M + dbms_security_auth_enabled: 'false' + ports: + - name: http + port: 7474 + - name: bolt + port: 7687 + resources: + requests: + memory: 512Mi + cpu: 200m + limits: + memory: 2Gi + cpu: 1000m + image: localhost:5000/workflows:latest + name: workflows + port: 8080 + resources: *id009 + sentry: + harness: + name: sentry + subdomain: errormonitor + domain: null + secured: false + uri_role_mapping: + - uri: /* + roles: + - administrator + deployment: + auto: true + replicas: 1 + image: localhost:5000/sentry:latest + name: sentry + port: 9000 + resources: &id010 + requests: + memory: 256Mi + cpu: 300m + limits: + memory: 2048Mi + cpu: 2000m + service: + auto: true + name: sentry + port: 9000 + database: + auto: false + name: sentry-db + type: null + size: 1Gi + user: mnp + pass: metacell + mongo: + image: mongo:latest + ports: + - name: http + port: 27017 + postgres: + image: postgres:latest + initialdb: cloudharness + ports: + - name: http + port: 5432 + neo4j: + image: neo4j:latest + memory: + size: 256M + pagecache: + size: 64M + heap: + initial: 64M + max: 128M + dbms_security_auth_enabled: 'false' + ports: + - name: http + port: 7474 + - name: bolt + port: 7687 + resources: + requests: + memory: 512Mi + cpu: 200m + limits: + memory: 2Gi + cpu: 1000m + postgres: + name: sentry-postgres-host + port: 5432 + image: postgres:latest + initialdb: sentry + user: sentry + password: secret + datavolume: /opt/data/ + pgdata: /opt/data/pgdata + redis: + name: sentry-redis-host + image: redis:latest + port: 6379 + postfix: + name: sentry-postfix-host + image: eeacms/postfix:latest + port: 25 + hostname: mail.opensourcebrain.org + image: localhost:5000/sentry:latest + name: sentry + port: 9000 + resources: *id010 +env: +- name: CH_VERSION + value: 0.0.1 +- name: CH_CHART_VERSION + value: 0.0.1 +- name: CH_VOLUMEMANAGER_NAME + value: volumemanager +- name: CH_VOLUMEMANAGER_SUBDOMAIN + value: volumemanager +- name: CH_ACCOUNTS_NAME + value: accounts +- name: CH_ACCOUNTS_SUBDOMAIN + value: accounts +- name: CH_SAMPLES_NAME + value: samples +- name: CH_SAMPLES_SUBDOMAIN + value: samples +- name: CH_SAMPLES_PORT + value: 80 +- name: CH_EVENTS_NAME + value: events +- name: CH_EVENTS_SUBDOMAIN + value: events +- name: CH_COMMON_NAME + value: common +- name: CH_COMMON_SUBDOMAIN + value: common +- name: CH_ARGO_NAME + value: argo-server +- name: CH_ARGO_SUBDOMAIN + value: argo +- name: CH_JUPYTERHUB_NAME + value: jupyterhub +- name: CH_JUPYTERHUB_SUBDOMAIN + value: jupyterhub +- name: CH_MYWEBAPP_NAME + value: mywebapp +- name: CH_MYWEBAPP_SUBDOMAIN + value: mywebapp +- name: CH_MYWEBAPP_PORT + value: 80 +- name: CH_WORKFLOWS_NAME + value: workflows +- name: CH_WORKFLOWS_SUBDOMAIN + value: workflows +- name: CH_SENTRY_NAME + value: sentry +- name: CH_SENTRY_SUBDOMAIN + value: errormonitor +- name: CH_DOMAIN + value: cloudharness.metacell.us +- name: CH_IMAGE_REGISTRY + value: localhost:5000/ +- name: CH_IMAGE_TAG + value: latest +- name: ARGO_INSTANCEID + value: ch +privenv: +- name: CH_SECRET + value: "In God we trust; all others must bring data. \u2015 W. Edwards Deming" +ingress: + enabled: true + name: cloudharness-ingress + ssl_redirect: false + letsencrypt: + email: filippo@metacell.us +tls: null +localIp: 192.168.99.104 +test: true diff --git a/utilities/MANIFEST.in b/utilities/MANIFEST.in index 34a27b48..f0ccd934 100644 --- a/utilities/MANIFEST.in +++ b/utilities/MANIFEST.in @@ -2,6 +2,6 @@ include cloudharness_utilities/deployment-configuration/* include cloudharness_utilities/deployment-configuration/**/* include cloudharness_utilities/deployment-configuration/**/**/* include cloudharness_utilities/deployment-configuration/**/**/**/* -include cloudharness_utilities/application-template/* -include cloudharness_utilities/application-template/**/* -include cloudharness_utilities/application-template/**/**/* \ No newline at end of file +include cloudharness_utilities/application-templates/* +include cloudharness_utilities/application-templates/**/* +include cloudharness_utilities/application-templates/**/**/* \ No newline at end of file diff --git a/utilities/README.md b/utilities/README.md index a1bbc44f..68c947b5 100644 --- a/utilities/README.md +++ b/utilities/README.md @@ -1,4 +1,4 @@ -#CloudHarness Deploy +# CloudHarness Deploy CloudHarness Deploy is a collection of Python utilities to create CloudHarness deployments. @@ -25,19 +25,19 @@ Usage: harness-application myapp ``` -For more info, `harness-application --help` - -## harness-codefresh +Other examples: -Generates the Codefresh continuous deployment specification. - -Usage: +Create a web application +```bash +harness-application myapp -t webapp +``` +Create a web application with Mongo database ```bash -harness-codefresh . +harness-application myapp -t webapp -t db-mongo ``` -For more info, `harness-codefresh --help` +For more info, `harness-application --help` ## harness-generate diff --git a/utilities/cloudharness_utilities/__init__.py b/utilities/cloudharness_utilities/__init__.py index b821e067..3ed6da4a 100644 --- a/utilities/cloudharness_utilities/__init__.py +++ b/utilities/cloudharness_utilities/__init__.py @@ -8,4 +8,4 @@ ] ) -HERE = os.path.dirname(os.path.realpath(__file__)) \ No newline at end of file +HERE = os.path.dirname(os.path.realpath(__file__)) diff --git a/utilities/cloudharness_utilities/application-template/api/config.json b/utilities/cloudharness_utilities/application-template/api/config.json deleted file mode 100644 index 0dd0c28f..00000000 --- a/utilities/cloudharness_utilities/application-template/api/config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "packageName": "api_samples" -} \ No newline at end of file diff --git a/utilities/cloudharness_utilities/application-template/api/openapi.yaml b/utilities/cloudharness_utilities/application-template/api/openapi.yaml deleted file mode 100644 index 691a41c9..00000000 --- a/utilities/cloudharness_utilities/application-template/api/openapi.yaml +++ /dev/null @@ -1,47 +0,0 @@ -openapi: 3.0.0 -info: - description: CloudHarness Sample api - version: 0.1.0 - title: CloudHarness Sample API - contact: - email: cloudharness@metacell.us - license: - name: UNLICENSED - -tags: - - name: auth - - name: workflows - -paths: - /test: - get: - summary: Test - security: - - bearerAuth: [] - tags: - - auth - operationId: test - description: | - Check if the token is valid - responses: - "200": - description: Check if the application works - "400": - description: bad input parameter - - -servers: - - url: https://samples.cloudharness.metacell.us/api -components: - securitySchemes: - bearerAuth: - type: http - scheme: bearer - bearerFormat: JWT - x-bearerInfoFunc: cloudharness.auth.decode_token - schemas: - Valid: - type: object - properties: - response: - type: string diff --git a/utilities/cloudharness_utilities/application-template/deploy/values.yaml b/utilities/cloudharness_utilities/application-template/deploy/values.yaml deleted file mode 100644 index 91949d61..00000000 --- a/utilities/cloudharness_utilities/application-template/deploy/values.yaml +++ /dev/null @@ -1,4 +0,0 @@ -port: 8080 -subdomain: samples -autodeploy: true -autoservice: true \ No newline at end of file diff --git a/utilities/cloudharness_utilities/application-templates/README.md b/utilities/cloudharness_utilities/application-templates/README.md new file mode 100644 index 00000000..0b2923f7 --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/README.md @@ -0,0 +1,7 @@ +# Application templates + +Add here all templates you want to merge/override +Follow the directory structure: +- base - those files are always added +- webapp - webapp scaffolding +- server - auto-generated server overriding files \ No newline at end of file diff --git a/utilities/cloudharness_utilities/application-templates/base/api/config.json b/utilities/cloudharness_utilities/application-templates/base/api/config.json new file mode 100644 index 00000000..06559b9a --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/base/api/config.json @@ -0,0 +1,3 @@ +{ + "packageName": "__APP_NAME__" +} \ No newline at end of file diff --git a/utilities/cloudharness_utilities/application-templates/base/api/openapi.yaml b/utilities/cloudharness_utilities/application-templates/base/api/openapi.yaml new file mode 100644 index 00000000..b3d81aaa --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/base/api/openapi.yaml @@ -0,0 +1,75 @@ +openapi: 3.0.0 +info: + description: __APP_NAME__ + version: 0.1.0 + title: __APP_NAME__ + contact: + email: cloudharness@metacell.us + license: + name: UNLICENSED + +tags: + - name: test + - name: live + - name: ready +paths: + /ping: + get: + summary: test the application is up + operationId: ping + tags: + - test + responses: + "500": + description: This shouldn't happen + "200": + description: What we want + content: + application/json: + schema: + type: string + /live: + get: + summary: Test if application is healthy + operationId: live + tags: + - live + responses: + "500": + description: Application is not healthy + "200": + description: Healthy + content: + application/json: + schema: + type: string + /ready: + get: + summary: Test if application is ready to take requests + operationId: ready + tags: + - ready + responses: + "500": + description: Application is not ready yet + "200": + description: Ready + content: + application/json: + schema: + type: string +servers: + - url: /api +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + x-bearerInfoFunc: cloudharness.auth.decode_token + schemas: + Valid: + type: object + properties: + response: + type: string diff --git a/utilities/cloudharness_utilities/application-templates/base/deploy/values.yaml b/utilities/cloudharness_utilities/application-templates/base/deploy/values.yaml new file mode 100644 index 00000000..95383400 --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/base/deploy/values.yaml @@ -0,0 +1,17 @@ +harness: + subdomain: __APP_NAME__ + secured: false + service: + port: 8080 + auto: true + deployment: + auto: true + port: 8080 + livenessProbe: + path: /api/live + readinessProbe: + path: /api/ready + dependencies: + build: + - cloudharness-base + - cloudharness-flask \ No newline at end of file diff --git a/utilities/cloudharness_utilities/application-templates/db-mongo/deploy/values.yaml b/utilities/cloudharness_utilities/application-templates/db-mongo/deploy/values.yaml new file mode 100644 index 00000000..f3519b50 --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/db-mongo/deploy/values.yaml @@ -0,0 +1,4 @@ +harness: + database: + auto: true + type: mongo \ No newline at end of file diff --git a/utilities/cloudharness_utilities/application-templates/db-neo4j/deploy/values.yaml b/utilities/cloudharness_utilities/application-templates/db-neo4j/deploy/values.yaml new file mode 100644 index 00000000..7ec22dab --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/db-neo4j/deploy/values.yaml @@ -0,0 +1,4 @@ +harness: + database: + auto: true + type: neo4j \ No newline at end of file diff --git a/utilities/cloudharness_utilities/application-templates/db-postgres/deploy/values.yaml b/utilities/cloudharness_utilities/application-templates/db-postgres/deploy/values.yaml new file mode 100644 index 00000000..4e3494db --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/db-postgres/deploy/values.yaml @@ -0,0 +1,4 @@ +harness: + database: + auto: true + type: postgres \ No newline at end of file diff --git a/utilities/cloudharness_utilities/application-templates/server/backend/.dockerignore b/utilities/cloudharness_utilities/application-templates/server/backend/.dockerignore new file mode 100644 index 00000000..a05d73b5 --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/server/backend/.dockerignore @@ -0,0 +1,71 @@ +.travis.yaml +.openapi-generator-ignore +README.md +tox.ini +git_push.sh +test-requirements.txt + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*,cover +.hypothesis/ +venv/ +.python-version + +# Translations +*.mo +*.pot + +# Django stuff: +*.log + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +#Ipython Notebook +.ipynb_checkpoints diff --git a/utilities/cloudharness_utilities/application-templates/server/backend/.openapi-generator-ignore b/utilities/cloudharness_utilities/application-templates/server/backend/.openapi-generator-ignore new file mode 100644 index 00000000..1b4d9526 --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/server/backend/.openapi-generator-ignore @@ -0,0 +1,29 @@ +# OpenAPI Generator Ignore +# Generated by openapi-generator https://github.com/openapitools/openapi-generator + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md +setup.py +*/controllers/* +Dockerfile +src/__main__.py +requirements.txt +test-requirements.txt \ No newline at end of file diff --git a/utilities/cloudharness_utilities/application-templates/server/backend/Dockerfile b/utilities/cloudharness_utilities/application-templates/server/backend/Dockerfile new file mode 100644 index 00000000..3e968c23 --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/server/backend/Dockerfile @@ -0,0 +1,19 @@ +ARG REGISTRY +ARG TAG=latest +ARG CLOUDHARNESS_FLASK=${REGISTRY}cloudharness-flask:${TAG} + +FROM $CLOUDHARNESS_FLASK + +ENV MODULE_NAME=__APP_NAME__ +ENV WORKERS=2 +ENV PORT=8080 + +COPY requirements.txt /usr/src/app/ + +RUN pip3 install --no-cache-dir -r requirements.txt + +COPY . /usr/src/app + +RUN pip3 install -e . + +ENTRYPOINT gunicorn --workers=$WORKERS --bind=0.0.0.0:$PORT $MODULE_NAME.__main__:app diff --git a/utilities/cloudharness_utilities/application-templates/server/backend/README.md b/utilities/cloudharness_utilities/application-templates/server/backend/README.md new file mode 100644 index 00000000..ede3b1d1 --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/server/backend/README.md @@ -0,0 +1,27 @@ +# __APP_NAME__ + +## Run +```bash +pip install -r requirements.txt +pip install -e . +python __main__.py +``` + +## Develop +The backend is a Python Flask application. +Connexion library maps the apis from the openapi definition to the Flask routing. + +### Implement api functions +Api functions are all defined inside [__APP_NAME__/controllers](__APP_NAME__/controllers). +Function stubs are automatically generated: just replace your function body with the desired code. +Since the stubs are automatically generated, using other modules outside the controllers as helpers and services to +implement the code logic is recommended. + +### Add api functions + +1. Edit [../api/openapi.yaml](api/openapi.yaml) as needed +1. Remove/comment the controllers exclusion on [.openapi-generator-ignore](.openapi-generator-ignore) file +1. Run `harness-generate .` from your deployment root +1. Merge the files inside [__APP_NAME__/controllers](__APP_NAME__/controllers). For instance, you can + use git or ide history) +1. Restore the [.openapi-generator-ignore](.openapi-generator-ignore) file \ No newline at end of file diff --git a/utilities/cloudharness_utilities/application-templates/server/backend/__APP_NAME__/__init__.py b/utilities/cloudharness_utilities/application-templates/server/backend/__APP_NAME__/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/utilities/cloudharness_utilities/application-templates/server/backend/__APP_NAME__/__main__.py b/utilities/cloudharness_utilities/application-templates/server/backend/__APP_NAME__/__main__.py new file mode 100644 index 00000000..1ce1af97 --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/server/backend/__APP_NAME__/__main__.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python3 + +from cloudharness.utils.server import init_flask, main + + +app = init_flask(title="__APP_NAME__", init_app_fn=None, webapp=False) + +if __name__ == '__main__': + main() + diff --git a/utilities/cloudharness_utilities/application-templates/server/backend/__APP_NAME__/helpers/README.md b/utilities/cloudharness_utilities/application-templates/server/backend/__APP_NAME__/helpers/README.md new file mode 100644 index 00000000..416d48b2 --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/server/backend/__APP_NAME__/helpers/README.md @@ -0,0 +1,4 @@ +# Controller helper modules functions + +Helpers implement specific parts of control logic. +Controllers delegate the business logic to helpers. \ No newline at end of file diff --git a/utilities/cloudharness_utilities/application-templates/server/backend/__APP_NAME__/helpers/__init__.py b/utilities/cloudharness_utilities/application-templates/server/backend/__APP_NAME__/helpers/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/utilities/cloudharness_utilities/application-templates/server/backend/__APP_NAME__/services/README.md b/utilities/cloudharness_utilities/application-templates/server/backend/__APP_NAME__/services/README.md new file mode 100644 index 00000000..d46309dd --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/server/backend/__APP_NAME__/services/README.md @@ -0,0 +1,3 @@ +# Service modules and functions + +Services map session-less logic around domain models. \ No newline at end of file diff --git a/utilities/cloudharness_utilities/application-templates/server/backend/__APP_NAME__/services/__init__.py b/utilities/cloudharness_utilities/application-templates/server/backend/__APP_NAME__/services/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/utilities/cloudharness_utilities/application-templates/webapp/.dockerignore b/utilities/cloudharness_utilities/application-templates/webapp/.dockerignore new file mode 100644 index 00000000..f06235c4 --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/webapp/.dockerignore @@ -0,0 +1,2 @@ +node_modules +dist diff --git a/utilities/cloudharness_utilities/application-templates/webapp/Dockerfile b/utilities/cloudharness_utilities/application-templates/webapp/Dockerfile new file mode 100644 index 00000000..d4285439 --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/webapp/Dockerfile @@ -0,0 +1,36 @@ +ARG REGISTRY +ARG TAG=latest +ARG CLOUDHARNESS_FRONTEND_BUILD=${REGISTRY}cloudharness-frontend-build:${TAG} +ARG CLOUDHARNESS_FLASK=${REGISTRY}cloudharness-flask:${TAG} + +FROM $CLOUDHARNESS_FRONTEND_BUILD as frontend + +ENV APP_DIR=/app + +WORKDIR ${APP_DIR} +COPY frontend/package.json ${APP_DIR} +COPY frontend/package-lock.json ${APP_DIR} +RUN npm ci + +COPY frontend ${APP_DIR} +RUN npm run build + +##### + +FROM $CLOUDHARNESS_FLASK + +ENV MODULE_NAME=__APP_NAME__ + +ENV WORKERS=2 +ENV PORT=8080 + +COPY backend/requirements.txt /usr/src/app/ + +RUN pip3 install --no-cache-dir -r requirements.txt + +COPY backend/ /usr/src/app +RUN pip3 install -e . + +COPY --from=frontend app/dist/ /usr/src/app/www + +ENTRYPOINT gunicorn --workers=$WORKERS --bind=0.0.0.0:$PORT $MODULE_NAME.__main__:app \ No newline at end of file diff --git a/utilities/cloudharness_utilities/application-templates/webapp/README.md b/utilities/cloudharness_utilities/application-templates/webapp/README.md new file mode 100644 index 00000000..15fe7369 --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/webapp/README.md @@ -0,0 +1,68 @@ +# __APP_NAME__ + +Flask/React-based web application. +This application is constructed to be deployed inside a cloud-harness Kubernetes. +It can be also run locally for development and test purpose. + +The code is generated with the script `harness-application` and is in part automatically generated +from [openapi definition](./api/config.json). + +## Run with Docker + +```bash +docker build . -t __APP_NAME__ +docker run -it -p 8080:8080 __APP_NAME__ +``` + +Prerequisite: the cloudharness-frontend-build image must be built first: + +```bash +cd [CLOUDHARNESS_ROOT] +docker build . -f infrastructure/base-images/cloudharness-frontend-build/Dockerfile -t cloudharness-frontend-build +``` + +## Develop + +This application is composed of a Flask backend and a React frontend. + +### Backend + +Backend code is inside the *backend* directory. +See [backend/README.md#Develop] + +### Frontend + +Backend code is inside the *frontend* directory. + +Frontend is by default generated as a React web application, but no constraint about this specific technology. + +#### Build and run + +To run in development mode: +```bash +cd frontend +npm install +npm run start +``` +This setup will start the application at http://localhost:9000. use the backend running at http://localhost:5000. +The backend can be either started from code or from Docker. +In that case the launch command needs to match the port with: + +```bash +docker run -it -p 5000:8080 __APP_NAME__ +``` + +#### Call the backend apis +All the api stubs are automatically generated in the [frontend/rest](frontend/rest) directory by `harness-application` +and `harness-generate`. + +## Local run + +```bash +cd frontend +npm install +npm run build +cp dist '../backend/www' -R +cd ../backend +python __main__.py +``` \ No newline at end of file diff --git a/utilities/cloudharness_utilities/application-templates/webapp/backend/__APP_NAME__/__main__.py b/utilities/cloudharness_utilities/application-templates/webapp/backend/__APP_NAME__/__main__.py new file mode 100644 index 00000000..c6becb11 --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/webapp/backend/__APP_NAME__/__main__.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python3 + +from cloudharness.utils.server import init_flask, main + + +app = init_flask(title="__APP_NAME__", init_app_fn=None, webapp=True) + +if __name__ == '__main__': + main() + diff --git a/utilities/cloudharness_utilities/application-templates/webapp/deploy/values.yaml b/utilities/cloudharness_utilities/application-templates/webapp/deploy/values.yaml new file mode 100644 index 00000000..498371df --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/webapp/deploy/values.yaml @@ -0,0 +1,6 @@ +harness: + dependencies: + build: + - cloudharness-base + - cloudharness-frontend-build + - cloudharness-flask \ No newline at end of file diff --git a/utilities/cloudharness_utilities/application-templates/webapp/frontend/.babelrc b/utilities/cloudharness_utilities/application-templates/webapp/frontend/.babelrc new file mode 100644 index 00000000..2b53150f --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/webapp/frontend/.babelrc @@ -0,0 +1,20 @@ +{ + "presets": [ + "@babel/preset-env", + "@babel/preset-react" + ], + "env": { + "production":{ + "presets": ["minify"] + } + }, + "plugins": [ + "@babel/transform-regenerator", + "@babel/plugin-proposal-class-properties", + [ + "module-resolver", { + "root": ["./src"] + } + ] + ] +} \ No newline at end of file diff --git a/utilities/cloudharness_utilities/application-templates/webapp/frontend/.dockerignore b/utilities/cloudharness_utilities/application-templates/webapp/frontend/.dockerignore new file mode 100644 index 00000000..cf709889 --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/webapp/frontend/.dockerignore @@ -0,0 +1 @@ +**/node_modules diff --git a/utilities/cloudharness_utilities/application-templates/webapp/frontend/.eslintignore b/utilities/cloudharness_utilities/application-templates/webapp/frontend/.eslintignore new file mode 100644 index 00000000..763301fc --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/webapp/frontend/.eslintignore @@ -0,0 +1,2 @@ +dist/ +node_modules/ \ No newline at end of file diff --git a/utilities/cloudharness_utilities/application-templates/webapp/frontend/.eslintrc.yml b/utilities/cloudharness_utilities/application-templates/webapp/frontend/.eslintrc.yml new file mode 100644 index 00000000..68fb53e5 --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/webapp/frontend/.eslintrc.yml @@ -0,0 +1,49 @@ +--- +root: true +extends: + - eslint:recommended + - plugin:react/recommended +parser: 'babel-eslint' +parserOptions: + ecmaFeatures: + jsx: true +plugins: + - jest + - react + - react-hooks +settings: + react: + version: detect +env: + jest/globals: true + browser: true + es6: true +rules: + no-console: 0 + func-style: 2 + consistent-return: 2 + prefer-arrow-callback: + - 2 + - allowNamedFunctions: false + allowUnboundThis: false + jest/no-disabled-tests: 2 + jest/no-focused-tests: 2 + react/prop-types: 0 + react/forbid-prop-types: 0 + react/no-unused-prop-types: 0 + react-hooks/rules-of-hooks: 2 + react-hooks/exhaustive-deps: 1 + curly: 2 + no-tabs: 2 + arrow-spacing: 2 + no-unneeded-ternary: 2 + object-curly-spacing: + - 2 + - always + indent: + - 2 + - 2 + - SwitchCase: 1 +globals: + __dirname: writable + module: writable \ No newline at end of file diff --git a/utilities/cloudharness_utilities/application-templates/webapp/frontend/.gitignore b/utilities/cloudharness_utilities/application-templates/webapp/frontend/.gitignore new file mode 100644 index 00000000..149b5765 --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/webapp/frontend/.gitignore @@ -0,0 +1,4 @@ +wwwroot/*.js +node_modules +typings +dist diff --git a/utilities/cloudharness_utilities/application-templates/webapp/frontend/README.md b/utilities/cloudharness_utilities/application-templates/webapp/frontend/README.md new file mode 100644 index 00000000..f55bdc5b --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/webapp/frontend/README.md @@ -0,0 +1 @@ +# __APP_NAME__ diff --git a/utilities/cloudharness_utilities/application-templates/webapp/frontend/build.yaml b/utilities/cloudharness_utilities/application-templates/webapp/frontend/build.yaml new file mode 100644 index 00000000..cbed1458 --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/webapp/frontend/build.yaml @@ -0,0 +1,2 @@ +build_arguments: + - MY_ARG=${{MY_ARG}} \ No newline at end of file diff --git a/utilities/cloudharness_utilities/application-templates/webapp/frontend/package-lock.json b/utilities/cloudharness_utilities/application-templates/webapp/frontend/package-lock.json new file mode 100644 index 00000000..9f88d053 --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/webapp/frontend/package-lock.json @@ -0,0 +1,8800 @@ +{ + "name": "samples", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/compat-data": { + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.12.7.tgz", + "integrity": "sha512-YaxPMGs/XIWtYqrdEOZOCPsVWfEoriXopnsz3/i7apYPXQ3698UFhS6dVT1KN5qOsWmVgw/FOrmQgpRaZayGsw==", + "dev": true + }, + "@babel/core": { + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.10.tgz", + "integrity": "sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.12.10", + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helpers": "^7.12.5", + "@babel/parser": "^7.12.10", + "@babel/template": "^7.12.7", + "@babel/traverse": "^7.12.10", + "@babel/types": "^7.12.10", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "semver": "^5.4.1", + "source-map": "^0.5.0" + } + }, + "@babel/generator": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.11.tgz", + "integrity": "sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA==", + "dev": true, + "requires": { + "@babel/types": "^7.12.11", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.10.tgz", + "integrity": "sha512-XplmVbC1n+KY6jL8/fgLVXXUauDIB+lD5+GsQEh6F6GBF1dq1qy4DP4yXWzDKcoqXB3X58t61e85Fitoww4JVQ==", + "dev": true, + "requires": { + "@babel/types": "^7.12.10" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz", + "integrity": "sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg==", + "dev": true, + "requires": { + "@babel/helper-explode-assignable-expression": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.5.tgz", + "integrity": "sha512-+qH6NrscMolUlzOYngSBMIOQpKUGPPsc61Bu5W10mg84LxZ7cmvnBHzARKbDoFxVvqqAbj6Tg6N7bSrWSPXMyw==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.12.5", + "@babel/helper-validator-option": "^7.12.1", + "browserslist": "^4.14.5", + "semver": "^5.5.0" + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.1.tgz", + "integrity": "sha512-hkL++rWeta/OVOBTRJc9a5Azh5mt5WgZUGAKMD8JM141YsE08K//bp1unBBieO6rUKkIPyUE0USQ30jAy3Sk1w==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-member-expression-to-functions": "^7.12.1", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/helper-replace-supers": "^7.12.1", + "@babel/helper-split-export-declaration": "^7.10.4" + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.7.tgz", + "integrity": "sha512-idnutvQPdpbduutvi3JVfEgcVIHooQnhvhx0Nk9isOINOIGYkZea1Pk2JlJRiUnMefrlvr0vkByATBY/mB4vjQ==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "regexpu-core": "^4.7.1" + } + }, + "@babel/helper-define-map": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz", + "integrity": "sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/types": "^7.10.5", + "lodash": "^4.17.19" + } + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.12.1.tgz", + "integrity": "sha512-dmUwH8XmlrUpVqgtZ737tK88v07l840z9j3OEhCLwKTkjlvKpfqXVIZ0wpK3aeOxspwGrf/5AP5qLx4rO3w5rA==", + "dev": true, + "requires": { + "@babel/types": "^7.12.1" + } + }, + "@babel/helper-function-name": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz", + "integrity": "sha512-AtQKjtYNolKNi6nNNVLQ27CP6D9oFR6bq/HPYSizlzbp7uC1M59XJe8L+0uXjbIaZaUJF99ruHqVGiKXU/7ybA==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.12.10", + "@babel/template": "^7.12.7", + "@babel/types": "^7.12.11" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz", + "integrity": "sha512-mm0n5BPjR06wh9mPQaDdXWDoll/j5UpCAPl1x8fS71GHm7HA6Ua2V4ylG1Ju8lvcTOietbPNNPaSilKj+pj+Ag==", + "dev": true, + "requires": { + "@babel/types": "^7.12.10" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz", + "integrity": "sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.7.tgz", + "integrity": "sha512-DCsuPyeWxeHgh1Dus7APn7iza42i/qXqiFPWyBDdOFtvS581JQePsc1F/nD+fHrcswhLlRc2UpYS1NwERxZhHw==", + "dev": true, + "requires": { + "@babel/types": "^7.12.7" + } + }, + "@babel/helper-module-imports": { + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz", + "integrity": "sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA==", + "dev": true, + "requires": { + "@babel/types": "^7.12.5" + } + }, + "@babel/helper-module-transforms": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz", + "integrity": "sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.12.1", + "@babel/helper-replace-supers": "^7.12.1", + "@babel/helper-simple-access": "^7.12.1", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/helper-validator-identifier": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.12.1", + "@babel/types": "^7.12.1", + "lodash": "^4.17.19" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.10.tgz", + "integrity": "sha512-4tpbU0SrSTjjt65UMWSrUOPZTsgvPgGG4S8QSTNHacKzpS51IVWGDj0yCwyeZND/i+LSN2g/O63jEXEWm49sYQ==", + "dev": true, + "requires": { + "@babel/types": "^7.12.10" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", + "dev": true + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.12.1.tgz", + "integrity": "sha512-9d0KQCRM8clMPcDwo8SevNs+/9a8yWVVmaE80FGJcEP8N1qToREmWEGnBn8BUlJhYRFz6fqxeRL1sl5Ogsed7A==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-wrap-function": "^7.10.4", + "@babel/types": "^7.12.1" + } + }, + "@babel/helper-replace-supers": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.11.tgz", + "integrity": "sha512-q+w1cqmhL7R0FNzth/PLLp2N+scXEK/L2AHbXUyydxp828F4FEa5WcVoqui9vFRiHDQErj9Zof8azP32uGVTRA==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.12.7", + "@babel/helper-optimise-call-expression": "^7.12.10", + "@babel/traverse": "^7.12.10", + "@babel/types": "^7.12.11" + } + }, + "@babel/helper-simple-access": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz", + "integrity": "sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA==", + "dev": true, + "requires": { + "@babel/types": "^7.12.1" + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz", + "integrity": "sha512-Mf5AUuhG1/OCChOJ/HcADmvcHM42WJockombn8ATJG3OnyiSxBK/Mm5x78BQWvmtXZKHgbjdGL2kin/HOLlZGA==", + "dev": true, + "requires": { + "@babel/types": "^7.12.1" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz", + "integrity": "sha512-LsIVN8j48gHgwzfocYUSkO/hjYAOJqlpJEc7tGXcIm4cubjVUf8LGW6eWRyxEu7gA25q02p0rQUWoCI33HNS5g==", + "dev": true, + "requires": { + "@babel/types": "^7.12.11" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.11.tgz", + "integrity": "sha512-TBFCyj939mFSdeX7U7DDj32WtzYY7fDcalgq8v3fBZMNOJQNn7nOYzMaUCiPxPYfCup69mtIpqlKgMZLvQ8Xhw==", + "dev": true + }, + "@babel/helper-wrap-function": { + "version": "7.12.3", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.12.3.tgz", + "integrity": "sha512-Cvb8IuJDln3rs6tzjW3Y8UeelAOdnpB8xtQ4sme2MSZ9wOxrbThporC0y/EtE16VAtoyEfLM404Xr1e0OOp+ow==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helpers": { + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.5.tgz", + "integrity": "sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA==", + "dev": true, + "requires": { + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.12.5", + "@babel/types": "^7.12.5" + } + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.11.tgz", + "integrity": "sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg==", + "dev": true + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.12.tgz", + "integrity": "sha512-nrz9y0a4xmUrRq51bYkWJIO5SBZyG2ys2qinHsN0zHDHVsUaModrkpyWWWXfGqYQmOL3x9sQIcTNN/pBGpo09A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-remap-async-to-generator": "^7.12.1", + "@babel/plugin-syntax-async-generators": "^7.8.0" + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz", + "integrity": "sha512-cKp3dlQsFsEs5CWKnN7BnSHOd0EOW8EKpEjkoz1pO2E5KzIDNV9Ros1b0CnmbVgAGXJubOYVBOGCT1OmJwOI7w==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-proposal-dynamic-import": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.1.tgz", + "integrity": "sha512-a4rhUSZFuq5W8/OO8H7BL5zspjnc1FLd9hlOxIK/f7qG4a0qsqk8uvF/ywgBA8/OmjsapjpvaEOYItfGG1qIvQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-dynamic-import": "^7.8.0" + } + }, + "@babel/plugin-proposal-export-namespace-from": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.12.1.tgz", + "integrity": "sha512-6CThGf0irEkzujYS5LQcjBx8j/4aQGiVv7J9+2f7pGfxqyKh3WnmVJYW3hdrQjyksErMGBPQrCnHfOtna+WLbw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.12.1.tgz", + "integrity": "sha512-GoLDUi6U9ZLzlSda2Df++VSqDJg3CG+dR0+iWsv6XRw1rEq+zwt4DirM9yrxW6XWaTpmai1cWJLMfM8qQJf+yw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.0" + } + }, + "@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.12.1.tgz", + "integrity": "sha512-k8ZmVv0JU+4gcUGeCDZOGd0lCIamU/sMtIiX3UWnUc5yzgq6YUGyEolNYD+MLYKfSzgECPcqetVcJP9Afe/aCA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.12.1.tgz", + "integrity": "sha512-nZY0ESiaQDI1y96+jk6VxMOaL4LPo/QDHBqL+SF3/vl6dHkTwHlOI8L4ZwuRBHgakRBw5zsVylel7QPbbGuYgg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" + } + }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.7.tgz", + "integrity": "sha512-8c+uy0qmnRTeukiGsjLGy6uVs/TFjJchGXUeBqlG4VWYOdJWkhhVPdQ3uHwbmalfJwv2JsV0qffXP4asRfL2SQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz", + "integrity": "sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-transform-parameters": "^7.12.1" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.12.1.tgz", + "integrity": "sha512-hFvIjgprh9mMw5v42sJWLI1lzU5L2sznP805zeT6rySVRA0Y18StRhDqhSxlap0oVgItRsB6WSROp4YnJTJz0g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" + } + }, + "@babel/plugin-proposal-optional-chaining": { + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.7.tgz", + "integrity": "sha512-4ovylXZ0PWmwoOvhU2vhnzVNnm88/Sm9nx7V8BPgMvAzn5zDou3/Awy0EjglyubVHasJj+XCEkr/r1X3P5elCA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-skip-transparent-expression-wrappers": "^7.12.1", + "@babel/plugin-syntax-optional-chaining": "^7.8.0" + } + }, + "@babel/plugin-proposal-private-methods": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.12.1.tgz", + "integrity": "sha512-mwZ1phvH7/NHK6Kf8LP7MYDogGV+DKB1mryFOEwx5EBNQrosvIczzZFTUmWaeujd5xT6G1ELYWUz3CutMhjE1w==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.1.tgz", + "integrity": "sha512-MYq+l+PvHuw/rKUz1at/vb6nCnQ2gmJBNaM62z0OgH7B2W1D9pvkpYtlti9bGtizNIU1K3zm4bZF9F91efVY0w==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.1.tgz", + "integrity": "sha512-U40A76x5gTwmESz+qiqssqmeEsKvcSyvtgktrm0uzcARAmM9I1jR221f6Oq+GmHrcD+LvZDag1UTOTe2fL3TeA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz", + "integrity": "sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.1.tgz", + "integrity": "sha512-i7ooMZFS+a/Om0crxZodrTzNEPJHZrlMVGMTEpFAj6rYY/bKCddB0Dk/YxfPuYXOopuhKk/e1jV6h+WUU9XN3A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.12.1.tgz", + "integrity": "sha512-5QB50qyN44fzzz4/qxDPQMBCTHgxg3n0xRBLJUmBlLoU/sFvxVWGZF/ZUfMVDQuJUKXaBhbupxIzIfZ6Fwk/0A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.12.1.tgz", + "integrity": "sha512-SDtqoEcarK1DFlRJ1hHRY5HvJUj5kX4qmtpMAm2QnhOlyuMC4TMdCRgW6WXpv93rZeYNeLP22y8Aq2dbcDRM1A==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-remap-async-to-generator": "^7.12.1" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.12.1.tgz", + "integrity": "sha512-5OpxfuYnSgPalRpo8EWGPzIYf0lHBWORCkj5M0oLBwHdlux9Ri36QqGW3/LR13RSVOAoUUMzoPI/jpE4ABcHoA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.12.tgz", + "integrity": "sha512-VOEPQ/ExOVqbukuP7BYJtI5ZxxsmegTwzZ04j1aF0dkSypGo9XpDHuOrABsJu+ie+penpSJheDJ11x1BEZNiyQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.12.1.tgz", + "integrity": "sha512-/74xkA7bVdzQTBeSUhLLJgYIcxw/dpEpCdRDiHgPJ3Mv6uC11UhjpOhl72CgqbBCmt1qtssCyB2xnJm1+PFjog==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-define-map": "^7.10.4", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.12.1", + "@babel/helper-split-export-declaration": "^7.10.4", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.12.1.tgz", + "integrity": "sha512-vVUOYpPWB7BkgUWPo4C44mUQHpTZXakEqFjbv8rQMg7TC6S6ZhGZ3otQcRH6u7+adSlE5i0sp63eMC/XGffrzg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.12.1.tgz", + "integrity": "sha512-fRMYFKuzi/rSiYb2uRLiUENJOKq4Gnl+6qOv5f8z0TZXg3llUwUhsNNwrwaT/6dUhJTzNpBr+CUvEWBtfNY1cw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.12.1.tgz", + "integrity": "sha512-B2pXeRKoLszfEW7J4Hg9LoFaWEbr/kzo3teWHmtFCszjRNa/b40f9mfeqZsIDLLt/FjwQ6pz/Gdlwy85xNckBA==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.12.1.tgz", + "integrity": "sha512-iRght0T0HztAb/CazveUpUQrZY+aGKKaWXMJ4uf9YJtqxSUe09j3wteztCUDRHs+SRAL7yMuFqUsLoAKKzgXjw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.12.1.tgz", + "integrity": "sha512-7tqwy2bv48q+c1EHbXK0Zx3KXd2RVQp6OC7PbwFNt/dPTAV3Lu5sWtWuAj8owr5wqtWnqHfl2/mJlUmqkChKug==", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.12.1.tgz", + "integrity": "sha512-Zaeq10naAsuHo7heQvyV0ptj4dlZJwZgNAtBYBnu5nNKJoW62m0zKcIEyVECrUKErkUkg6ajMy4ZfnVZciSBhg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.12.1.tgz", + "integrity": "sha512-JF3UgJUILoFrFMEnOJLJkRHSk6LUSXLmEFsA23aR2O5CSLUxbeUX1IZ1YQ7Sn0aXb601Ncwjx73a+FVqgcljVw==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.12.1.tgz", + "integrity": "sha512-+PxVGA+2Ag6uGgL0A5f+9rklOnnMccwEBzwYFL3EUaKuiyVnUipyXncFcfjSkbimLrODoqki1U9XxZzTvfN7IQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.12.1.tgz", + "integrity": "sha512-1sxePl6z9ad0gFMB9KqmYofk34flq62aqMt9NqliS/7hPEpURUCMbyHXrMPlo282iY7nAvUB1aQd5mg79UD9Jg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.12.1.tgz", + "integrity": "sha512-tDW8hMkzad5oDtzsB70HIQQRBiTKrhfgwC/KkJeGsaNFTdWhKNt/BiE8c5yj19XiGyrxpbkOfH87qkNg1YGlOQ==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.12.1.tgz", + "integrity": "sha512-dY789wq6l0uLY8py9c1B48V8mVL5gZh/+PQ5ZPrylPYsnAvnEMjqsUXkuoDVPeVK+0VyGar+D08107LzDQ6pag==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-simple-access": "^7.12.1", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.12.1.tgz", + "integrity": "sha512-Hn7cVvOavVh8yvW6fLwveFqSnd7rbQN3zJvoPNyNaQSvgfKmDBO9U1YL9+PCXGRlZD9tNdWTy5ACKqMuzyn32Q==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.10.4", + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-validator-identifier": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.12.1.tgz", + "integrity": "sha512-aEIubCS0KHKM0zUos5fIoQm+AZUMt1ZvMpqz0/H5qAQ7vWylr9+PLYurT+Ic7ID/bKLd4q8hDovaG3Zch2uz5Q==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.12.1.tgz", + "integrity": "sha512-tB43uQ62RHcoDp9v2Nsf+dSM8sbNodbEicbQNA53zHz8pWUhsgHSJCGpt7daXxRydjb0KnfmB+ChXOv3oADp1Q==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.12.1" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.12.1.tgz", + "integrity": "sha512-+eW/VLcUL5L9IvJH7rT1sT0CzkdUTvPrXC2PXTn/7z7tXLBuKvezYbGdxD5WMRoyvyaujOq2fWoKl869heKjhw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.12.1.tgz", + "integrity": "sha512-AvypiGJH9hsquNUn+RXVcBdeE3KHPZexWRdimhuV59cSoOt5kFBmqlByorAeUlGG2CJWd0U+4ZtNKga/TB0cAw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.12.1" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.12.1.tgz", + "integrity": "sha512-xq9C5EQhdPK23ZeCdMxl8bbRnAgHFrw5EOC3KJUsSylZqdkCaFEXxGSBuTSObOpiiHHNyb82es8M1QYgfQGfNg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.12.1.tgz", + "integrity": "sha512-6MTCR/mZ1MQS+AwZLplX4cEySjCpnIF26ToWo942nqn8hXSm7McaHQNeGx/pt7suI1TWOWMfa/NgBhiqSnX0cQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-react-display-name": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.12.1.tgz", + "integrity": "sha512-cAzB+UzBIrekfYxyLlFqf/OagTvHLcVBb5vpouzkYkBclRPraiygVnafvAoipErZLI8ANv8Ecn6E/m5qPXD26w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-react-jsx": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.12.tgz", + "integrity": "sha512-JDWGuzGNWscYcq8oJVCtSE61a5+XAOos+V0HrxnDieUus4UMnBEosDnY1VJqU5iZ4pA04QY7l0+JvHL1hZEfsw==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.12.10", + "@babel/helper-module-imports": "^7.12.5", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-jsx": "^7.12.1", + "@babel/types": "^7.12.12" + } + }, + "@babel/plugin-transform-react-jsx-development": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.12.12.tgz", + "integrity": "sha512-i1AxnKxHeMxUaWVXQOSIco4tvVvvCxMSfeBMnMM06mpaJt3g+MpxYQQrDfojUQldP1xxraPSJYSMEljoWM/dCg==", + "dev": true, + "requires": { + "@babel/plugin-transform-react-jsx": "^7.12.12" + } + }, + "@babel/plugin-transform-react-pure-annotations": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.12.1.tgz", + "integrity": "sha512-RqeaHiwZtphSIUZ5I85PEH19LOSzxfuEazoY7/pWASCAIBuATQzpSVD+eT6MebeeZT2F4eSL0u4vw6n4Nm0Mjg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.12.1.tgz", + "integrity": "sha512-gYrHqs5itw6i4PflFX3OdBPMQdPbF4bj2REIUxlMRUFk0/ZOAIpDFuViuxPjUL7YC8UPnf+XG7/utJvqXdPKng==", + "dev": true, + "requires": { + "regenerator-transform": "^0.14.2" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.12.1.tgz", + "integrity": "sha512-pOnUfhyPKvZpVyBHhSBoX8vfA09b7r00Pmm1sH+29ae2hMTKVmSp4Ztsr8KBKjLjx17H0eJqaRC3bR2iThM54A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.1.tgz", + "integrity": "sha512-GFZS3c/MhX1OusqB1MZ1ct2xRzX5ppQh2JU1h2Pnfk88HtFTM+TWQqJNfwkmxtPQtb/s1tk87oENfXJlx7rSDw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.12.1.tgz", + "integrity": "sha512-vuLp8CP0BE18zVYjsEBZ5xoCecMK6LBMMxYzJnh01rxQRvhNhH1csMMmBfNo5tGpGO+NhdSNW2mzIvBu3K1fng==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-skip-transparent-expression-wrappers": "^7.12.1" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.7.tgz", + "integrity": "sha512-VEiqZL5N/QvDbdjfYQBhruN0HYjSPjC4XkeqW4ny/jNtH9gcbgaqBIXYEZCNnESMAGs0/K/R7oFGMhOyu/eIxg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.12.1.tgz", + "integrity": "sha512-b4Zx3KHi+taXB1dVRBhVJtEPi9h1THCeKmae2qP0YdUHIFhVjtpqqNfxeVAa1xeHVhAy4SbHxEwx5cltAu5apw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.10.tgz", + "integrity": "sha512-JQ6H8Rnsogh//ijxspCjc21YPd3VLVoYtAwv3zQmqAt8YGYUtdo5usNhdl4b9/Vir2kPFZl6n1h0PfUz4hJhaA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.12.1.tgz", + "integrity": "sha512-I8gNHJLIc7GdApm7wkVnStWssPNbSRMPtgHdmH3sRM1zopz09UWPS4x5V4n1yz/MIWTVnJ9sp6IkuXdWM4w+2Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.1.tgz", + "integrity": "sha512-SqH4ClNngh/zGwHZOOQMTD+e8FGWexILV+ePMyiDJttAWRh5dhDL8rcl5lSgU3Huiq6Zn6pWTMvdPAb21Dwdyg==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.12.1", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/preset-env": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.12.11.tgz", + "integrity": "sha512-j8Tb+KKIXKYlDBQyIOy4BLxzv1NUOwlHfZ74rvW+Z0Gp4/cI2IMDPBWAgWceGcE7aep9oL/0K9mlzlMGxA8yNw==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.12.7", + "@babel/helper-compilation-targets": "^7.12.5", + "@babel/helper-module-imports": "^7.12.5", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-validator-option": "^7.12.11", + "@babel/plugin-proposal-async-generator-functions": "^7.12.1", + "@babel/plugin-proposal-class-properties": "^7.12.1", + "@babel/plugin-proposal-dynamic-import": "^7.12.1", + "@babel/plugin-proposal-export-namespace-from": "^7.12.1", + "@babel/plugin-proposal-json-strings": "^7.12.1", + "@babel/plugin-proposal-logical-assignment-operators": "^7.12.1", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1", + "@babel/plugin-proposal-numeric-separator": "^7.12.7", + "@babel/plugin-proposal-object-rest-spread": "^7.12.1", + "@babel/plugin-proposal-optional-catch-binding": "^7.12.1", + "@babel/plugin-proposal-optional-chaining": "^7.12.7", + "@babel/plugin-proposal-private-methods": "^7.12.1", + "@babel/plugin-proposal-unicode-property-regex": "^7.12.1", + "@babel/plugin-syntax-async-generators": "^7.8.0", + "@babel/plugin-syntax-class-properties": "^7.12.1", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.0", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.0", + "@babel/plugin-syntax-top-level-await": "^7.12.1", + "@babel/plugin-transform-arrow-functions": "^7.12.1", + "@babel/plugin-transform-async-to-generator": "^7.12.1", + "@babel/plugin-transform-block-scoped-functions": "^7.12.1", + "@babel/plugin-transform-block-scoping": "^7.12.11", + "@babel/plugin-transform-classes": "^7.12.1", + "@babel/plugin-transform-computed-properties": "^7.12.1", + "@babel/plugin-transform-destructuring": "^7.12.1", + "@babel/plugin-transform-dotall-regex": "^7.12.1", + "@babel/plugin-transform-duplicate-keys": "^7.12.1", + "@babel/plugin-transform-exponentiation-operator": "^7.12.1", + "@babel/plugin-transform-for-of": "^7.12.1", + "@babel/plugin-transform-function-name": "^7.12.1", + "@babel/plugin-transform-literals": "^7.12.1", + "@babel/plugin-transform-member-expression-literals": "^7.12.1", + "@babel/plugin-transform-modules-amd": "^7.12.1", + "@babel/plugin-transform-modules-commonjs": "^7.12.1", + "@babel/plugin-transform-modules-systemjs": "^7.12.1", + "@babel/plugin-transform-modules-umd": "^7.12.1", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.12.1", + "@babel/plugin-transform-new-target": "^7.12.1", + "@babel/plugin-transform-object-super": "^7.12.1", + "@babel/plugin-transform-parameters": "^7.12.1", + "@babel/plugin-transform-property-literals": "^7.12.1", + "@babel/plugin-transform-regenerator": "^7.12.1", + "@babel/plugin-transform-reserved-words": "^7.12.1", + "@babel/plugin-transform-shorthand-properties": "^7.12.1", + "@babel/plugin-transform-spread": "^7.12.1", + "@babel/plugin-transform-sticky-regex": "^7.12.7", + "@babel/plugin-transform-template-literals": "^7.12.1", + "@babel/plugin-transform-typeof-symbol": "^7.12.10", + "@babel/plugin-transform-unicode-escapes": "^7.12.1", + "@babel/plugin-transform-unicode-regex": "^7.12.1", + "@babel/preset-modules": "^0.1.3", + "@babel/types": "^7.12.11", + "core-js-compat": "^3.8.0", + "semver": "^5.5.0" + } + }, + "@babel/preset-modules": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz", + "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + } + }, + "@babel/preset-react": { + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.12.10.tgz", + "integrity": "sha512-vtQNjaHRl4DUpp+t+g4wvTHsLQuye+n0H/wsXIZRn69oz/fvNC7gQ4IK73zGJBaxvHoxElDvnYCthMcT7uzFoQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-transform-react-display-name": "^7.12.1", + "@babel/plugin-transform-react-jsx": "^7.12.10", + "@babel/plugin-transform-react-jsx-development": "^7.12.7", + "@babel/plugin-transform-react-pure-annotations": "^7.12.1" + } + }, + "@babel/runtime": { + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz", + "integrity": "sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/template": { + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.7.tgz", + "integrity": "sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.12.7", + "@babel/types": "^7.12.7" + } + }, + "@babel/traverse": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.12.tgz", + "integrity": "sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.11", + "@babel/generator": "^7.12.11", + "@babel/helper-function-name": "^7.12.11", + "@babel/helper-split-export-declaration": "^7.12.11", + "@babel/parser": "^7.12.11", + "@babel/types": "^7.12.12", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.19" + } + }, + "@babel/types": { + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", + "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "@discoveryjs/json-ext": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz", + "integrity": "sha512-HyYEUDeIj5rRQU2Hk5HTB2uHsbRQpF70nvMhVzi+VJR0X+xNEhjPui4/kBf3VeH/wqD28PT4sVOm8qqLjBrSZg==", + "dev": true + }, + "@nodelib/fs.scandir": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", + "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.4", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", + "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", + "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.4", + "fastq": "^1.6.0" + } + }, + "@npmcli/move-file": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.0.1.tgz", + "integrity": "sha512-Uv6h1sT+0DrblvIrolFtbvM1FgWm+/sy4B3pvLp67Zys+thcukzS5ekn7HsZFGpWP4Q3fYJCljbWQE/XivMRLw==", + "dev": true, + "requires": { + "mkdirp": "^1.0.4" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + } + } + }, + "@types/anymatch": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz", + "integrity": "sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==", + "dev": true + }, + "@types/eslint": { + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.2.6.tgz", + "integrity": "sha512-I+1sYH+NPQ3/tVqCeUSBwTE/0heyvtXqpIopUUArlBm0Kpocb8FbMa3AZ/ASKIFpN3rnEx932TTXDbt9OXsNDw==", + "dev": true, + "requires": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "@types/eslint-scope": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.0.tgz", + "integrity": "sha512-O/ql2+rrCUe2W2rs7wMR+GqPRcgB6UiqN5RhrR5xruFlY7l9YLMn0ZkDzjoHLeiFkR8MCQZVudUuuvQ2BLC9Qw==", + "dev": true, + "requires": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "@types/estree": { + "version": "0.0.45", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.45.tgz", + "integrity": "sha512-jnqIUKDUqJbDIUxm0Uj7bnlMnRm1T/eZ9N+AVMqhPgzrba2GhGG5o/jCTwmdPK709nEZsGoMzXEDUjcXHa3W0g==", + "dev": true + }, + "@types/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", + "dev": true, + "requires": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/html-minifier-terser": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", + "integrity": "sha512-giAlZwstKbmvMk1OO7WXSj4OZ0keXAcl2TQq4LWHiiPH2ByaH7WeUzng+Qej8UPxxv+8lRTuouo0iaNDBuzIBA==", + "dev": true + }, + "@types/json-schema": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", + "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==", + "dev": true + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, + "@types/node": { + "version": "14.14.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.20.tgz", + "integrity": "sha512-Y93R97Ouif9JEOWPIUyU+eyIdyRqQR0I8Ez1dzku4hDx34NWh4HbtIc3WNzwB1Y9ULvNGeu5B8h8bVL5cAk4/A==", + "dev": true + }, + "@types/source-list-map": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", + "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", + "dev": true + }, + "@types/tapable": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.6.tgz", + "integrity": "sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA==", + "dev": true + }, + "@types/uglify-js": { + "version": "3.11.1", + "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.11.1.tgz", + "integrity": "sha512-7npvPKV+jINLu1SpSYVWG8KvyJBhBa8tmzMMdDoVc2pWUYHN8KIXlPJhjJ4LT97c4dXJA2SHL/q6ADbDriZN+Q==", + "dev": true, + "requires": { + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "@types/webpack": { + "version": "4.41.25", + "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.25.tgz", + "integrity": "sha512-cr6kZ+4m9lp86ytQc1jPOJXgINQyz3kLLunZ57jznW+WIAL0JqZbGubQk4GlD42MuQL5JGOABrxdpqqWeovlVQ==", + "dev": true, + "requires": { + "@types/anymatch": "*", + "@types/node": "*", + "@types/tapable": "*", + "@types/uglify-js": "*", + "@types/webpack-sources": "*", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "@types/webpack-sources": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-2.1.0.tgz", + "integrity": "sha512-LXn/oYIpBeucgP1EIJbKQ2/4ZmpvRl+dlrFdX7+94SKRUV3Evy3FsfMZY318vGhkWUS5MPhtOM3w1/hCOAOXcg==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/source-list-map": "*", + "source-map": "^0.7.3" + }, + "dependencies": { + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + } + } + }, + "@typescript-eslint/experimental-utils": { + "version": "2.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.34.0.tgz", + "integrity": "sha512-eS6FTkq+wuMJ+sgtuNTtcqavWXqsflWcfBnlYhg/nS4aZ1leewkXGbvBhaapn1q6qf4M71bsR1tez5JTRMuqwA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/typescript-estree": "2.34.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^2.0.0" + }, + "dependencies": { + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + } + } + }, + "@typescript-eslint/typescript-estree": { + "version": "2.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.34.0.tgz", + "integrity": "sha512-OMAr+nJWKdlVM9LOqCqh3pQQPwxHAN7Du8DR6dmwCrAmxtiXQnhHJ6tBNtf+cggqfo51SG/FCwnKhXCIM7hnVg==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "eslint-visitor-keys": "^1.1.0", + "glob": "^7.1.6", + "is-glob": "^4.0.1", + "lodash": "^4.17.15", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@webassemblyjs/ast": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.0.tgz", + "integrity": "sha512-kX2W49LWsbthrmIRMbQZuQDhGtjyqXfEmmHyEi4XWnSZtPmxY0+3anPIzsnRb45VH/J55zlOfWvZuY47aJZTJg==", + "dev": true, + "requires": { + "@webassemblyjs/helper-numbers": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.0.tgz", + "integrity": "sha512-Q/aVYs/VnPDVYvsCBL/gSgwmfjeCb4LW8+TMrO3cSzJImgv8lxxEPM2JA5jMrivE7LSz3V+PFqtMbls3m1exDA==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.0.tgz", + "integrity": "sha512-baT/va95eXiXb2QflSx95QGT5ClzWpGaa8L7JnJbgzoYeaA27FCvuBXU758l+KXWRndEmUXjP0Q5fibhavIn8w==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.0.tgz", + "integrity": "sha512-u9HPBEl4DS+vA8qLQdEQ6N/eJQ7gT7aNvMIo8AAWvAl/xMrcOSiI2M0MAnMCy3jIFke7bEee/JwdX1nUpCtdyA==", + "dev": true + }, + "@webassemblyjs/helper-numbers": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.0.tgz", + "integrity": "sha512-DhRQKelIj01s5IgdsOJMKLppI+4zpmcMQ3XboFPLwCpSNH6Hqo1ritgHgD0nqHeSYqofA6aBN/NmXuGjM1jEfQ==", + "dev": true, + "requires": { + "@webassemblyjs/floating-point-hex-parser": "1.11.0", + "@webassemblyjs/helper-api-error": "1.11.0", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.0.tgz", + "integrity": "sha512-MbmhvxXExm542tWREgSFnOVo07fDpsBJg3sIl6fSp9xuu75eGz5lz31q7wTLffwL3Za7XNRCMZy210+tnsUSEA==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.0.tgz", + "integrity": "sha512-3Eb88hcbfY/FCukrg6i3EH8H2UsD7x8Vy47iVJrP967A9JGqgBVL9aH71SETPx1JrGsOUVLo0c7vMCN22ytJew==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-buffer": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0", + "@webassemblyjs/wasm-gen": "1.11.0" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.0.tgz", + "integrity": "sha512-KXzOqpcYQwAfeQ6WbF6HXo+0udBNmw0iXDmEK5sFlmQdmND+tr773Ti8/5T/M6Tl/413ArSJErATd8In3B+WBA==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.0.tgz", + "integrity": "sha512-aqbsHa1mSQAbeeNcl38un6qVY++hh8OpCOzxhixSYgbRfNWcxJNJQwe2rezK9XEcssJbbWIkblaJRwGMS9zp+g==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.0.tgz", + "integrity": "sha512-A/lclGxH6SpSLSyFowMzO/+aDEPU4hvEiooCMXQPcQFPPJaYcPQNKGOCLUySJsYJ4trbpr+Fs08n4jelkVTGVw==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.0.tgz", + "integrity": "sha512-JHQ0damXy0G6J9ucyKVXO2j08JVJ2ntkdJlq1UTiUrIgfGMmA7Ik5VdC/L8hBK46kVJgujkBIoMtT8yVr+yVOQ==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-buffer": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0", + "@webassemblyjs/helper-wasm-section": "1.11.0", + "@webassemblyjs/wasm-gen": "1.11.0", + "@webassemblyjs/wasm-opt": "1.11.0", + "@webassemblyjs/wasm-parser": "1.11.0", + "@webassemblyjs/wast-printer": "1.11.0" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.0.tgz", + "integrity": "sha512-BEUv1aj0WptCZ9kIS30th5ILASUnAPEvE3tVMTrItnZRT9tXCLW2LEXT8ezLw59rqPP9klh9LPmpU+WmRQmCPQ==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0", + "@webassemblyjs/ieee754": "1.11.0", + "@webassemblyjs/leb128": "1.11.0", + "@webassemblyjs/utf8": "1.11.0" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.0.tgz", + "integrity": "sha512-tHUSP5F4ywyh3hZ0+fDQuWxKx3mJiPeFufg+9gwTpYp324mPCQgnuVKwzLTZVqj0duRDovnPaZqDwoyhIO8kYg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-buffer": "1.11.0", + "@webassemblyjs/wasm-gen": "1.11.0", + "@webassemblyjs/wasm-parser": "1.11.0" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.0.tgz", + "integrity": "sha512-6L285Sgu9gphrcpDXINvm0M9BskznnzJTE7gYkjDbxET28shDqp27wpruyx3C2S/dvEwiigBwLA1cz7lNUi0kw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/helper-api-error": "1.11.0", + "@webassemblyjs/helper-wasm-bytecode": "1.11.0", + "@webassemblyjs/ieee754": "1.11.0", + "@webassemblyjs/leb128": "1.11.0", + "@webassemblyjs/utf8": "1.11.0" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.0.tgz", + "integrity": "sha512-Fg5OX46pRdTgB7rKIUojkh9vXaVN6sGYCnEiJN1GYkb0RPwShZXp6KTDqmoMdQPKhcroOXh3fEzmkWmCYaKYhQ==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.0", + "@xtuc/long": "4.2.2" + } + }, + "@webpack-cli/info": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.2.1.tgz", + "integrity": "sha512-fLnDML5HZ5AEKzHul8xLAksoKN2cibu6MgonkUj8R9V7bbeVRkd1XbGEGWrAUNYHbX1jcqCsDEpBviE5StPMzQ==", + "dev": true, + "requires": { + "envinfo": "^7.7.3" + } + }, + "@webpack-cli/serve": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.2.1.tgz", + "integrity": "sha512-Zj1z6AyS+vqV6Hfi7ngCjFGdHV5EwZNIHo6QfFTNe9PyW+zBU1zJ9BiOW1pmUEq950RC4+Dym6flyA/61/vhyw==", + "dev": true + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "dev": true + }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "dev": true + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true + }, + "ansi-colors": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", + "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", + "dev": true + }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-html": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", + "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", + "dev": true + }, + "array-includes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.2.tgz", + "integrity": "sha512-w2GspexNQpx+PutG3QpT437/BenZBj0M/MZGn5mzv/MofYqo0xmRHzn4lFsoDlWJ+THYsGJmFlW68WlDFx7VRw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "get-intrinsic": "^1.0.1", + "is-string": "^1.0.5" + } + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "array.prototype.flatmap": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.4.tgz", + "integrity": "sha512-r9Z0zYoxqHz60vvQbWEdXIEtCwHF0yxaWfno9qzXeNHvfyl3BZqygmGzb84dsubyaXLH4husF+NFgMSdpZhk2Q==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "function-bind": "^1.1.1" + } + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "ast-types": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.9.6.tgz", + "integrity": "sha1-ECyenpAF0+fjgpvwxPok7oYu6bk=", + "dev": true + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "awesome-typescript-loader": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/awesome-typescript-loader/-/awesome-typescript-loader-5.2.1.tgz", + "integrity": "sha512-slv66OAJB8orL+UUaTI3pKlLorwIvS4ARZzYR9iJJyGsEgOqueMfOMdKySWzZ73vIkEe3fcwFgsKMg4d8zyb1g==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "enhanced-resolve": "^4.0.0", + "loader-utils": "^1.1.0", + "lodash": "^4.17.5", + "micromatch": "^3.1.9", + "mkdirp": "^0.5.1", + "source-map-support": "^0.5.3", + "webpack-log": "^1.2.0" + } + }, + "axios": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", + "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", + "requires": { + "follow-redirects": "^1.10.0" + } + }, + "babel-eslint": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", + "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.7.0", + "@babel/traverse": "^7.7.0", + "@babel/types": "^7.7.0", + "eslint-visitor-keys": "^1.0.0", + "resolve": "^1.12.0" + } + }, + "babel-helper-evaluate-path": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-helper-evaluate-path/-/babel-helper-evaluate-path-0.5.0.tgz", + "integrity": "sha512-mUh0UhS607bGh5wUMAQfOpt2JX2ThXMtppHRdRU1kL7ZLRWIXxoV2UIV1r2cAeeNeU1M5SB5/RSUgUxrK8yOkA==", + "dev": true + }, + "babel-helper-flip-expressions": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-helper-flip-expressions/-/babel-helper-flip-expressions-0.4.3.tgz", + "integrity": "sha1-NpZzahKKwYvCUlS19AoizrPB0/0=", + "dev": true + }, + "babel-helper-is-nodes-equiv": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/babel-helper-is-nodes-equiv/-/babel-helper-is-nodes-equiv-0.0.1.tgz", + "integrity": "sha1-NOmzALFHnd2Y7HfqC76TQt/jloQ=", + "dev": true + }, + "babel-helper-is-void-0": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-helper-is-void-0/-/babel-helper-is-void-0-0.4.3.tgz", + "integrity": "sha1-fZwBtFYee5Xb2g9u7kj1tg5nMT4=", + "dev": true + }, + "babel-helper-mark-eval-scopes": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-helper-mark-eval-scopes/-/babel-helper-mark-eval-scopes-0.4.3.tgz", + "integrity": "sha1-0kSjvvmESHJgP/tG4izorN9VFWI=", + "dev": true + }, + "babel-helper-remove-or-void": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-helper-remove-or-void/-/babel-helper-remove-or-void-0.4.3.tgz", + "integrity": "sha1-pPA7QAd6D/6I5F0HAQ3uJB/1rmA=", + "dev": true + }, + "babel-helper-to-multiple-sequence-expressions": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-helper-to-multiple-sequence-expressions/-/babel-helper-to-multiple-sequence-expressions-0.5.0.tgz", + "integrity": "sha512-m2CvfDW4+1qfDdsrtf4dwOslQC3yhbgyBFptncp4wvtdrDHqueW7slsYv4gArie056phvQFhT2nRcGS4bnm6mA==", + "dev": true + }, + "babel-loader": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.2.tgz", + "integrity": "sha512-JvTd0/D889PQBtUXJ2PXaKU/pjZDMtHA9V2ecm+eNRmmBCMR09a+fmpGTNwnJtFmFl5Ei7Vy47LjBb+L0wQ99g==", + "dev": true, + "requires": { + "find-cache-dir": "^3.3.1", + "loader-utils": "^1.4.0", + "make-dir": "^3.1.0", + "schema-utils": "^2.6.5" + } + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "dev": true, + "requires": { + "object.assign": "^4.1.0" + } + }, + "babel-plugin-minify-builtins": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-builtins/-/babel-plugin-minify-builtins-0.5.0.tgz", + "integrity": "sha512-wpqbN7Ov5hsNwGdzuzvFcjgRlzbIeVv1gMIlICbPj0xkexnfoIDe7q+AZHMkQmAE/F9R5jkrB6TLfTegImlXag==", + "dev": true + }, + "babel-plugin-minify-constant-folding": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-constant-folding/-/babel-plugin-minify-constant-folding-0.5.0.tgz", + "integrity": "sha512-Vj97CTn/lE9hR1D+jKUeHfNy+m1baNiJ1wJvoGyOBUx7F7kJqDZxr9nCHjO/Ad+irbR3HzR6jABpSSA29QsrXQ==", + "dev": true, + "requires": { + "babel-helper-evaluate-path": "^0.5.0" + } + }, + "babel-plugin-minify-dead-code-elimination": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-dead-code-elimination/-/babel-plugin-minify-dead-code-elimination-0.5.1.tgz", + "integrity": "sha512-x8OJOZIrRmQBcSqxBcLbMIK8uPmTvNWPXH2bh5MDCW1latEqYiRMuUkPImKcfpo59pTUB2FT7HfcgtG8ZlR5Qg==", + "dev": true, + "requires": { + "babel-helper-evaluate-path": "^0.5.0", + "babel-helper-mark-eval-scopes": "^0.4.3", + "babel-helper-remove-or-void": "^0.4.3", + "lodash": "^4.17.11" + } + }, + "babel-plugin-minify-flip-comparisons": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-flip-comparisons/-/babel-plugin-minify-flip-comparisons-0.4.3.tgz", + "integrity": "sha1-AMqHDLjxO0XAOLPB68DyJyk8llo=", + "dev": true, + "requires": { + "babel-helper-is-void-0": "^0.4.3" + } + }, + "babel-plugin-minify-guarded-expressions": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-guarded-expressions/-/babel-plugin-minify-guarded-expressions-0.4.4.tgz", + "integrity": "sha512-RMv0tM72YuPPfLT9QLr3ix9nwUIq+sHT6z8Iu3sLbqldzC1Dls8DPCywzUIzkTx9Zh1hWX4q/m9BPoPed9GOfA==", + "dev": true, + "requires": { + "babel-helper-evaluate-path": "^0.5.0", + "babel-helper-flip-expressions": "^0.4.3" + } + }, + "babel-plugin-minify-infinity": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-infinity/-/babel-plugin-minify-infinity-0.4.3.tgz", + "integrity": "sha1-37h2obCKBldjhO8/kuZTumB7Oco=", + "dev": true + }, + "babel-plugin-minify-mangle-names": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-mangle-names/-/babel-plugin-minify-mangle-names-0.5.0.tgz", + "integrity": "sha512-3jdNv6hCAw6fsX1p2wBGPfWuK69sfOjfd3zjUXkbq8McbohWy23tpXfy5RnToYWggvqzuMOwlId1PhyHOfgnGw==", + "dev": true, + "requires": { + "babel-helper-mark-eval-scopes": "^0.4.3" + } + }, + "babel-plugin-minify-numeric-literals": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-numeric-literals/-/babel-plugin-minify-numeric-literals-0.4.3.tgz", + "integrity": "sha1-jk/VYcefeAEob/YOjF/Z3u6TwLw=", + "dev": true + }, + "babel-plugin-minify-replace": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-replace/-/babel-plugin-minify-replace-0.5.0.tgz", + "integrity": "sha512-aXZiaqWDNUbyNNNpWs/8NyST+oU7QTpK7J9zFEFSA0eOmtUNMU3fczlTTTlnCxHmq/jYNFEmkkSG3DDBtW3Y4Q==", + "dev": true + }, + "babel-plugin-minify-simplify": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-simplify/-/babel-plugin-minify-simplify-0.5.1.tgz", + "integrity": "sha512-OSYDSnoCxP2cYDMk9gxNAed6uJDiDz65zgL6h8d3tm8qXIagWGMLWhqysT6DY3Vs7Fgq7YUDcjOomhVUb+xX6A==", + "dev": true, + "requires": { + "babel-helper-evaluate-path": "^0.5.0", + "babel-helper-flip-expressions": "^0.4.3", + "babel-helper-is-nodes-equiv": "^0.0.1", + "babel-helper-to-multiple-sequence-expressions": "^0.5.0" + } + }, + "babel-plugin-minify-type-constructors": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-type-constructors/-/babel-plugin-minify-type-constructors-0.4.3.tgz", + "integrity": "sha1-G8bxW4f3qxCF1CszC3F2V6IVZQA=", + "dev": true, + "requires": { + "babel-helper-is-void-0": "^0.4.3" + } + }, + "babel-plugin-module-resolver": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-4.1.0.tgz", + "integrity": "sha512-MlX10UDheRr3lb3P0WcaIdtCSRlxdQsB1sBqL7W0raF070bGl1HQQq5K3T2vf2XAYie+ww+5AKC/WrkjRO2knA==", + "dev": true, + "requires": { + "find-babel-config": "^1.2.0", + "glob": "^7.1.6", + "pkg-up": "^3.1.0", + "reselect": "^4.0.0", + "resolve": "^1.13.1" + } + }, + "babel-plugin-transform-inline-consecutive-adds": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-inline-consecutive-adds/-/babel-plugin-transform-inline-consecutive-adds-0.4.3.tgz", + "integrity": "sha1-Mj1Ho+pjqDp6w8gRro5pQfrysNE=", + "dev": true + }, + "babel-plugin-transform-member-expression-literals": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-member-expression-literals/-/babel-plugin-transform-member-expression-literals-6.9.4.tgz", + "integrity": "sha1-NwOcmgwzE6OUlfqsL/OmtbnQOL8=", + "dev": true + }, + "babel-plugin-transform-merge-sibling-variables": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-merge-sibling-variables/-/babel-plugin-transform-merge-sibling-variables-6.9.4.tgz", + "integrity": "sha1-hbQi/DN3tEnJ0c3kQIcgNTJAHa4=", + "dev": true + }, + "babel-plugin-transform-minify-booleans": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-minify-booleans/-/babel-plugin-transform-minify-booleans-6.9.4.tgz", + "integrity": "sha1-rLs+VqNVXdI5KOS1gtKFFi3SsZg=", + "dev": true + }, + "babel-plugin-transform-property-literals": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.9.4.tgz", + "integrity": "sha1-mMHSHiVXNlc/k+zlRFn2ziSYXTk=", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "babel-plugin-transform-regexp-constructors": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regexp-constructors/-/babel-plugin-transform-regexp-constructors-0.4.3.tgz", + "integrity": "sha1-WLd3W2OvzzMyj66aX4j71PsLSWU=", + "dev": true + }, + "babel-plugin-transform-remove-console": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-console/-/babel-plugin-transform-remove-console-6.9.4.tgz", + "integrity": "sha1-uYA2DAZzhOJLNXpYjYB9PINSd4A=", + "dev": true + }, + "babel-plugin-transform-remove-debugger": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-debugger/-/babel-plugin-transform-remove-debugger-6.9.4.tgz", + "integrity": "sha1-QrcnYxyXl44estGZp67IShgznvI=", + "dev": true + }, + "babel-plugin-transform-remove-undefined": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-undefined/-/babel-plugin-transform-remove-undefined-0.5.0.tgz", + "integrity": "sha512-+M7fJYFaEE/M9CXa0/IRkDbiV3wRELzA1kKQFCJ4ifhrzLKn/9VCCgj9OFmYWwBd8IB48YdgPkHYtbYq+4vtHQ==", + "dev": true, + "requires": { + "babel-helper-evaluate-path": "^0.5.0" + } + }, + "babel-plugin-transform-simplify-comparison-operators": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-simplify-comparison-operators/-/babel-plugin-transform-simplify-comparison-operators-6.9.4.tgz", + "integrity": "sha1-9ir+CWyrDh9ootdT/fKDiIRxzrk=", + "dev": true + }, + "babel-plugin-transform-undefined-to-void": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-undefined-to-void/-/babel-plugin-transform-undefined-to-void-6.9.4.tgz", + "integrity": "sha1-viQcqBQEAwZ4t0hxcyK4nQyP4oA=", + "dev": true + }, + "babel-preset-minify": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/babel-preset-minify/-/babel-preset-minify-0.5.1.tgz", + "integrity": "sha512-1IajDumYOAPYImkHbrKeiN5AKKP9iOmRoO2IPbIuVp0j2iuCcj0n7P260z38siKMZZ+85d3mJZdtW8IgOv+Tzg==", + "dev": true, + "requires": { + "babel-plugin-minify-builtins": "^0.5.0", + "babel-plugin-minify-constant-folding": "^0.5.0", + "babel-plugin-minify-dead-code-elimination": "^0.5.1", + "babel-plugin-minify-flip-comparisons": "^0.4.3", + "babel-plugin-minify-guarded-expressions": "^0.4.4", + "babel-plugin-minify-infinity": "^0.4.3", + "babel-plugin-minify-mangle-names": "^0.5.0", + "babel-plugin-minify-numeric-literals": "^0.4.3", + "babel-plugin-minify-replace": "^0.5.0", + "babel-plugin-minify-simplify": "^0.5.1", + "babel-plugin-minify-type-constructors": "^0.4.3", + "babel-plugin-transform-inline-consecutive-adds": "^0.4.3", + "babel-plugin-transform-member-expression-literals": "^6.9.4", + "babel-plugin-transform-merge-sibling-variables": "^6.9.4", + "babel-plugin-transform-minify-booleans": "^6.9.4", + "babel-plugin-transform-property-literals": "^6.9.4", + "babel-plugin-transform-regexp-constructors": "^0.4.3", + "babel-plugin-transform-remove-console": "^6.9.4", + "babel-plugin-transform-remove-debugger": "^6.9.4", + "babel-plugin-transform-remove-undefined": "^0.5.0", + "babel-plugin-transform-simplify-comparison-operators": "^6.9.4", + "babel-plugin-transform-undefined-to-void": "^6.9.4", + "lodash": "^4.17.11" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", + "dev": true + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dev": true, + "requires": { + "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" + }, + "dependencies": { + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", + "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", + "dev": true, + "requires": { + "array-flatten": "^2.1.0", + "deep-equal": "^1.0.1", + "dns-equal": "^1.0.0", + "dns-txt": "^2.0.2", + "multicast-dns": "^6.0.1", + "multicast-dns-service-types": "^1.1.0" + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "browserslist": { + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.1.tgz", + "integrity": "sha512-UXhDrwqsNcpTYJBTZsbGATDxZbiVDsx6UjpmRUmtnP10pr8wAYr5LgFoEFw9ixriQH2mv/NX2SfGzE/o8GndLA==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001173", + "colorette": "^1.2.1", + "electron-to-chromium": "^1.3.634", + "escalade": "^3.1.1", + "node-releases": "^1.1.69" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "buffer-indexof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", + "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", + "dev": true + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "call-bind": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.1.tgz", + "integrity": "sha512-tvAvUwNcRikl3RVF20X9lsYmmepsovzTWeJiXjO0PkJp15uy/6xKFZOQtuiSULwYW+6ToZBprphCgWXC2dSgcQ==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camel-case": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", + "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", + "dev": true, + "requires": { + "no-case": "^2.2.0", + "upper-case": "^1.1.1" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30001174", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001174.tgz", + "integrity": "sha512-tqClL/4ThQq6cfFXH3oJL4rifFBeM6gTkphjao5kgwMaW9yn0tKgQLAEfKzDwj6HQWCB/aWo8kTFlSvIN8geEA==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "dependencies": { + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + } + } + }, + "chrome-trace-event": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", + "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "clean-css": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", + "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==", + "dev": true, + "requires": { + "source-map": "~0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true + }, + "clean-webpack-plugin": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/clean-webpack-plugin/-/clean-webpack-plugin-3.0.0.tgz", + "integrity": "sha512-MciirUH5r+cYLGCOL5JX/ZLzOZbVr1ot3Fw+KcvbhUb6PM+yycqd9ZhIlcigQ5gl+XhppNmw3bEFuaaMNyLj3A==", + "dev": true, + "requires": { + "@types/webpack": "^4.4.31", + "del": "^4.1.1" + } + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-width": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", + "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", + "dev": true + }, + "clipboard-copy": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/clipboard-copy/-/clipboard-copy-3.2.0.tgz", + "integrity": "sha512-vooFaGFL6ulEP1liiaWFBmmfuPm3cY3y7T9eB83ZTnYc/oFeAKsq3NcDrOkBC8XaauEE8zHQwI7k0+JSYiVQSQ==" + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "colorette": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz", + "integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==", + "dev": true + }, + "commander": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "compression-webpack-plugin": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/compression-webpack-plugin/-/compression-webpack-plugin-7.1.2.tgz", + "integrity": "sha512-9DKNW6ILLjx+bNBoviHDgLx6swBhWWH9ApClC9sTH2NoFfQM47BapQfovCm9zjD9v1uZwInF5a925FB9ErGQeQ==", + "dev": true, + "requires": { + "schema-utils": "^3.0.0", + "serialize-javascript": "^5.0.1" + }, + "dependencies": { + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "connect-history-api-fallback": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", + "dev": true + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "dev": true + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "copy-anything": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.1.tgz", + "integrity": "sha512-lA57e7viQHOdPQcrytv5jFeudZZOXuyk47lZym279FiDQ8jeZomXiGuVf6ffMKkJ+3TIai3J1J3yi6M+/4U35g==", + "dev": true, + "requires": { + "is-what": "^3.7.1" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "copy-webpack-plugin": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-6.4.1.tgz", + "integrity": "sha512-MXyPCjdPVx5iiWyl40Va3JGh27bKzOTNY3NjUTrosD2q7dR/cLD0013uqJ3BpFbUjyONINjb6qI7nDIJujrMbA==", + "dev": true, + "requires": { + "cacache": "^15.0.5", + "fast-glob": "^3.2.4", + "find-cache-dir": "^3.3.1", + "glob-parent": "^5.1.1", + "globby": "^11.0.1", + "loader-utils": "^2.0.0", + "normalize-path": "^3.0.0", + "p-limit": "^3.0.2", + "schema-utils": "^3.0.0", + "serialize-javascript": "^5.0.1", + "webpack-sources": "^1.4.3" + }, + "dependencies": { + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "cacache": { + "version": "15.0.5", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.5.tgz", + "integrity": "sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A==", + "dev": true, + "requires": { + "@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.0", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + } + }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true + }, + "globby": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.2.tgz", + "integrity": "sha512-2ZThXDvvV8fYFRVIxnrMQBipZQDr7MxKAmQK1vujaj9/7eF0efG7BPUKJ7jP7G5SLF37xKDXvO4S/KKLj/Z0og==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + } + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "ssri": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.0.tgz", + "integrity": "sha512-aq/pz989nxVYwn16Tsbj1TqFpD5LLrQxHf5zaHuieFV+R0Bbr4y8qUsOA45hXT/N4/9UNXTarBjnjVmjSOVaAA==", + "dev": true, + "requires": { + "minipass": "^3.1.1" + } + } + } + }, + "core-js-compat": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.8.2.tgz", + "integrity": "sha512-LO8uL9lOIyRRrQmZxHZFl1RV+ZbcsAkFWTktn5SmH40WgLtSNYN4m4W2v9ONT147PxBY/XrRhrWq8TlvObyUjQ==", + "dev": true, + "requires": { + "browserslist": "^4.16.0", + "semver": "7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true + } + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "css-loader": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", + "integrity": "sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "cssesc": "^3.0.0", + "icss-utils": "^4.1.1", + "loader-utils": "^1.2.3", + "normalize-path": "^3.0.0", + "postcss": "^7.0.32", + "postcss-modules-extract-imports": "^2.0.0", + "postcss-modules-local-by-default": "^3.0.2", + "postcss-modules-scope": "^2.2.0", + "postcss-modules-values": "^3.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^2.7.0", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "css-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", + "dev": true, + "requires": { + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "css-what": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", + "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==", + "dev": true + }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true + }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "deep-equal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", + "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "dev": true, + "requires": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" + } + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "default-gateway": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", + "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==", + "dev": true, + "requires": { + "execa": "^1.0.0", + "ip-regex": "^2.1.0" + } + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "del": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", + "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "globby": "^6.1.0", + "is-path-cwd": "^2.0.0", + "is-path-in-cwd": "^2.0.0", + "p-map": "^2.0.0", + "pify": "^4.0.1", + "rimraf": "^2.6.3" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "detect-node": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", + "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==", + "dev": true + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", + "dev": true + }, + "dns-packet": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz", + "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==", + "dev": true, + "requires": { + "ip": "^1.1.0", + "safe-buffer": "^5.0.1" + } + }, + "dns-txt": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", + "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", + "dev": true, + "requires": { + "buffer-indexof": "^1.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dev": true, + "requires": { + "utila": "~0.4" + } + }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.1.0.tgz", + "integrity": "sha512-LsTgx/L5VpD+Q8lmsXSHW2WpA+eBlZ9HPf3erD1IoPF00/3JKHZ3BknUVA2QGDNu69ZNmyFmCWBSO45XjYKC5w==", + "dev": true + } + } + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "dev": true, + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + }, + "dependencies": { + "lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "requires": { + "tslib": "^2.0.3" + } + }, + "no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "requires": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", + "dev": true + } + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.635", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.635.tgz", + "integrity": "sha512-RRriZOLs9CpW6KTLmgBqyUdnY0QNqqWs0HOtuQGGEMizOTNNn1P7sGRBxARnUeLejOsgwjDyRqT3E/CSst02ZQ==", + "dev": true + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "enhanced-resolve": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", + "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + } + }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + }, + "dependencies": { + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + } + } + }, + "entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "dev": true + }, + "envinfo": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.7.3.tgz", + "integrity": "sha512-46+j5QxbPWza0PB1i15nZx0xQ4I/EfQxg9J8Had3b408SV63nEtor2e+oiY63amTo9KTuh2a3XLObNwduxYwwA==", + "dev": true + }, + "errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, + "requires": { + "prr": "~1.0.1" + } + }, + "es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "dev": true, + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "es6-templates": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/es6-templates/-/es6-templates-0.2.3.tgz", + "integrity": "sha1-XLmsn7He1usSOTQrgdeSu7QHjuQ=", + "dev": true, + "requires": { + "recast": "~0.11.12", + "through": "~2.3.6" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", + "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.9.1", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^4.0.3", + "eslint-utils": "^1.3.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^5.0.1", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^6.2.2", + "js-yaml": "^3.13.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.11", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^5.5.1", + "strip-ansi": "^4.0.0", + "strip-json-comments": "^2.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0" + }, + "dependencies": { + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + } + } + }, + "eslint-plugin-jest": { + "version": "23.20.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-23.20.0.tgz", + "integrity": "sha512-+6BGQt85OREevBDWCvhqj1yYA4+BFK4XnRZSGJionuEYmcglMZYLNNBBemwzbqUAckURaHdJSBcjHPyrtypZOw==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "^2.5.0" + } + }, + "eslint-plugin-react": { + "version": "7.22.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.22.0.tgz", + "integrity": "sha512-p30tuX3VS+NWv9nQot9xIGAHBXR0+xJVaZriEsHoJrASGCJZDJ8JLNM0YqKqI0AKm6Uxaa1VUHoNEibxRCMQHA==", + "dev": true, + "requires": { + "array-includes": "^3.1.1", + "array.prototype.flatmap": "^1.2.3", + "doctrine": "^2.1.0", + "has": "^1.0.3", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "object.entries": "^1.1.2", + "object.fromentries": "^2.0.2", + "object.values": "^1.1.1", + "prop-types": "^15.7.2", + "resolve": "^1.18.1", + "string.prototype.matchall": "^4.0.2" + }, + "dependencies": { + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + } + } + }, + "eslint-plugin-react-hooks": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-3.0.0.tgz", + "integrity": "sha512-EjxTHxjLKIBWFgDJdhKKzLh5q+vjTFrqNZX36uIxWS4OfyXe5DawqPj3U5qeJ1ngLwatjzQnmR0Lz0J0YH3kxw==", + "dev": true + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + }, + "espree": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", + "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", + "dev": true, + "requires": { + "acorn": "^6.0.7", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", + "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true + }, + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "events": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz", + "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==", + "dev": true + }, + "eventsource": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz", + "integrity": "sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==", + "dev": true, + "requires": { + "original": "^1.0.0" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dev": true, + "requires": { + "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" + }, + "dependencies": { + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + } + } + }, + "ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "dev": true, + "requires": { + "type": "^2.0.0" + }, + "dependencies": { + "type": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz", + "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==", + "dev": true + } + } + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-glob": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", + "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==", + "dev": true, + "requires": { + "@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" + }, + "dependencies": { + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + } + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fastest-levenshtein": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", + "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", + "dev": true + }, + "fastparse": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", + "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==", + "dev": true + }, + "fastq": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.10.0.tgz", + "integrity": "sha512-NL2Qc5L3iQEsyYzweq7qfgy5OtXCmGzGvhElGEd/SoFWEMOEczNh5s5ocaF01HDetxz+p8ecjNPA6cZxxIHmzA==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "faye-websocket": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", + "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, + "file-loader": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-5.1.0.tgz", + "integrity": "sha512-u/VkLGskw3Ue59nyOwUwXI/6nuBCo7KBkniB/l7ICwr/7cPNGsL1WCXUp3GB0qgOOKU1TiP49bv4DZF/LJqprg==", + "dev": true, + "requires": { + "loader-utils": "^1.4.0", + "schema-utils": "^2.5.0" + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "requires": { + "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" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "find-babel-config": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-1.2.0.tgz", + "integrity": "sha512-jB2CHJeqy6a820ssiqwrKMeyC6nNdmrcgkKWJWmpoxpE8RKciYJXCcXRq1h2AzCo5I5BJeN2tkGEO3hLTuePRA==", + "dev": true, + "requires": { + "json5": "^0.5.1", + "path-exists": "^3.0.0" + }, + "dependencies": { + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + } + } + }, + "find-cache-dir": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", + "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + }, + "dependencies": { + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "flatted": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "dev": true + }, + "follow-redirects": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.1.tgz", + "integrity": "sha512-SSG5xmZh1mkPGyKzjZP8zLjltIfpW32Y5QpdNJyjcfGxK3qo3NDDkZOZSFiGn1A6SclQxY9GzEwAHQ3dmYRWpg==" + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "dev": true + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true + }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-intrinsic": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.2.tgz", + "integrity": "sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "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" + } + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "history": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", + "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", + "requires": { + "@babel/runtime": "^7.1.2", + "loose-envify": "^1.2.0", + "resolve-pathname": "^3.0.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0", + "value-equal": "^1.0.1" + } + }, + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "^16.7.0" + } + }, + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "html-entities": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.4.0.tgz", + "integrity": "sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA==", + "dev": true + }, + "html-loader": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-0.5.5.tgz", + "integrity": "sha512-7hIW7YinOYUpo//kSYcPB6dCKoceKLmOwjEMmhIobHuWGDVl0Nwe4l68mdG/Ru0wcUxQjVMEoZpkalZ/SE7zog==", + "dev": true, + "requires": { + "es6-templates": "^0.2.3", + "fastparse": "^1.1.1", + "html-minifier": "^3.5.8", + "loader-utils": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "html-minifier": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz", + "integrity": "sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==", + "dev": true, + "requires": { + "camel-case": "3.0.x", + "clean-css": "4.2.x", + "commander": "2.17.x", + "he": "1.2.x", + "param-case": "2.1.x", + "relateurl": "0.2.x", + "uglify-js": "3.4.x" + } + }, + "html-minifier-terser": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", + "integrity": "sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg==", + "dev": true, + "requires": { + "camel-case": "^4.1.1", + "clean-css": "^4.2.3", + "commander": "^4.1.1", + "he": "^1.2.0", + "param-case": "^3.0.3", + "relateurl": "^0.2.7", + "terser": "^4.6.3" + }, + "dependencies": { + "camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "requires": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true + }, + "param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dev": true, + "requires": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + } + } + }, + "tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", + "dev": true + } + } + }, + "html-webpack-plugin": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-4.5.1.tgz", + "integrity": "sha512-yzK7RQZwv9xB+pcdHNTjcqbaaDZ+5L0zJHXfi89iWIZmb/FtzxhLk0635rmJihcQbs3ZUF27Xp4oWGx6EK56zg==", + "dev": true, + "requires": { + "@types/html-minifier-terser": "^5.0.0", + "@types/tapable": "^1.0.5", + "@types/webpack": "^4.41.8", + "html-minifier-terser": "^5.0.1", + "loader-utils": "^1.2.3", + "lodash": "^4.17.20", + "pretty-error": "^2.1.1", + "tapable": "^1.1.3", + "util.promisify": "1.0.0" + } + }, + "htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "dev": true, + "requires": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", + "dev": true + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", + "dev": true + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } + } + }, + "http-parser-js": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.3.tgz", + "integrity": "sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==", + "dev": true + }, + "http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-proxy-middleware": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz", + "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==", + "dev": true, + "requires": { + "http-proxy": "^1.17.0", + "is-glob": "^4.0.0", + "lodash": "^4.17.11", + "micromatch": "^3.1.10" + } + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "icss-utils": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", + "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", + "dev": true, + "requires": { + "postcss": "^7.0.14" + } + }, + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + }, + "image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", + "dev": true, + "optional": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + } + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", + "dev": true + }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "dev": true, + "requires": { + "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.12", + "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" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "internal-ip": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", + "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==", + "dev": true, + "requires": { + "default-gateway": "^4.2.0", + "ipaddr.js": "^1.9.0" + } + }, + "internal-slot": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.2.tgz", + "integrity": "sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g==", + "dev": true, + "requires": { + "es-abstract": "^1.17.0-next.1", + "has": "^1.0.3", + "side-channel": "^1.0.2" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, + "interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "dev": true + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + }, + "ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", + "dev": true + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true + }, + "is-absolute-url": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", + "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", + "dev": true + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-arguments": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz", + "integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==", + "dev": true, + "requires": { + "call-bind": "^1.0.0" + } + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-callable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", + "dev": true + }, + "is-core-module": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", + "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-negative-zero": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "dev": true + }, + "is-path-in-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", + "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", + "dev": true, + "requires": { + "is-path-inside": "^2.1.0" + } + }, + "is-path-inside": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", + "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", + "dev": true, + "requires": { + "path-is-inside": "^1.0.2" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-what": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.12.0.tgz", + "integrity": "sha512-2ilQz5/f/o9V7WRWJQmpFYNmQFZ9iM+OXRonZKcYgTkCzjb949Vi4h282PD1UfmgHk666rcWonbRJ++KI41VGw==", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json3": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz", + "integrity": "sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==", + "dev": true + }, + "json5": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "jsx-ast-utils": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.0.tgz", + "integrity": "sha512-EIsmt3O3ljsU6sot/J4E1zDRxfBNrhjyf/OKjlydwgEimQuznlM4Wv7U+ueONJMyEn1WRE0K8dhi3dVAXYT24Q==", + "dev": true, + "requires": { + "array-includes": "^3.1.2", + "object.assign": "^4.1.2" + } + }, + "killable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", + "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==", + "dev": true + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "less": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/less/-/less-3.13.1.tgz", + "integrity": "sha512-SwA1aQXGUvp+P5XdZslUOhhLnClSLIjWvJhmd+Vgib5BFIr9lMNlQwmwUNOjXThF/A0x+MCYYPeWEfeWiLRnTw==", + "dev": true, + "requires": { + "copy-anything": "^2.0.1", + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "make-dir": "^2.1.0", + "mime": "^1.4.1", + "native-request": "^1.0.5", + "source-map": "~0.6.0", + "tslib": "^1.10.0" + }, + "dependencies": { + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "optional": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + } + } + }, + "less-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-5.0.0.tgz", + "integrity": "sha512-bquCU89mO/yWLaUq0Clk7qCsKhsF/TZpJUzETRvJa9KSVEL9SO3ovCvdEHISBhrC81OwC8QSVX7E0bzElZj9cg==", + "dev": true, + "requires": { + "clone": "^2.1.1", + "loader-utils": "^1.1.0", + "pify": "^4.0.1" + } + }, + "less-vars-to-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/less-vars-to-js/-/less-vars-to-js-1.3.0.tgz", + "integrity": "sha512-xeiLLn/IMCGtdyCkYQnW8UuzoW2oYMCKg9boZRaGI58fLz5r90bNJDlqGzmVt/1Uqk75/DxIVtQSNCMkE5fRZQ==", + "dev": true, + "requires": { + "strip-json-comments": "^2.0.1" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "loader-runner": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", + "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", + "dev": true + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + } + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "requires": { + "chalk": "^2.0.1" + } + }, + "loglevel": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz", + "integrity": "sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==", + "dev": true + }, + "loglevelnext": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-1.0.5.tgz", + "integrity": "sha512-V/73qkPuJmx4BcBF19xPBr+0ZRVBhc4POxvZTZdMeXpJ4NItXSJ/MSwuFT0kQJlCbXvdlZoQQ/418bS1y9Jh6A==", + "dev": true, + "requires": { + "es6-symbol": "^3.1.1", + "object.assign": "^4.1.0" + } + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "lower-case": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", + "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", + "dev": true + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "mime-db": { + "version": "1.45.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", + "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==", + "dev": true + }, + "mime-types": { + "version": "2.1.28", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz", + "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==", + "dev": true, + "requires": { + "mime-db": "1.45.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "mini-create-react-context": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz", + "integrity": "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==", + "requires": { + "@babel/runtime": "^7.12.1", + "tiny-warning": "^1.0.3" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "minipass": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + } + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", + "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "dev": true, + "requires": { + "dns-packet": "^1.3.1", + "thunky": "^1.0.2" + } + }, + "multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", + "dev": true + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "nan": { + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", + "dev": true, + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "native-request": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/native-request/-/native-request-1.0.8.tgz", + "integrity": "sha512-vU2JojJVelUGp6jRcLwToPoWGxSx23z/0iX+I77J3Ht17rf2INGjrhOoQnjVo60nQd8wVsgzKkPfRXBiVdD2ag==", + "dev": true, + "optional": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "no-case": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", + "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "dev": true, + "requires": { + "lower-case": "^1.1.1" + } + }, + "node-forge": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", + "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==", + "dev": true + }, + "node-releases": { + "version": "1.1.69", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.69.tgz", + "integrity": "sha512-DGIjo79VDEyAnRlfSqYTsy+yoHd2IOjJiKUozD2MV2D85Vso6Bug56mb9tT/fY5Urt0iqk01H7x+llAruDR2zA==", + "dev": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "dev": true, + "requires": { + "boolbase": "~1.0.0" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-inspect": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", + "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==", + "dev": true + }, + "object-is": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.4.tgz", + "integrity": "sha512-1ZvAZ4wlF7IyPVOcE1Omikt7UpaFlOQq0HlSti+ZvDH3UiD2brwGMwDbyV43jao2bKJ+4+WdPJHSd7kgzKYVqg==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + }, + "object.entries": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.3.tgz", + "integrity": "sha512-ym7h7OZebNS96hn5IJeyUmaWhaSM4SVtAPPfNLQEI2MYWCO2egsITb9nab2+i/Pwibx+R0mtn+ltKJXRSeTMGg==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "has": "^1.0.3" + } + }, + "object.fromentries": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.3.tgz", + "integrity": "sha512-IDUSMXs6LOSJBWE++L0lzIbSqHl9KDCfff2x/JSEIDtEUavUnyMYC2ZGay/04Zq4UT8lvd4xNhU4/YHKibAOlw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "has": "^1.0.3" + } + }, + "object.getownpropertydescriptors": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.1.tgz", + "integrity": "sha512-6DtXgZ/lIZ9hqx4GtZETobXLR/ZLaa0aqV0kzbn80Rf8Z2e/XFnhA0I7p07N2wH8bBBltr2xQPi6sbKWAY2Eng==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "object.values": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.2.tgz", + "integrity": "sha512-MYC0jvJopr8EK6dPBiO8Nb9mvjdypOachO5REGk6MXzujbBrAisKo3HmdEI6kZDL6fC31Mwee/5YbtMebixeag==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "has": "^1.0.3" + } + }, + "obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "opn": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", + "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", + "dev": true, + "requires": { + "is-wsl": "^1.1.0" + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "original": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", + "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", + "dev": true, + "requires": { + "url-parse": "^1.4.3" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + }, + "p-retry": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", + "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==", + "dev": true, + "requires": { + "retry": "^0.12.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "param-case": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", + "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", + "dev": true, + "requires": { + "no-case": "^2.2.0" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true + }, + "pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dev": true, + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + }, + "dependencies": { + "lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "requires": { + "tslib": "^2.0.3" + } + }, + "no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "requires": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", + "dev": true + } + } + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "requires": { + "isarray": "0.0.1" + } + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + } + } + }, + "portfinder": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", + "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", + "dev": true, + "requires": { + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.5" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-modules-extract-imports": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", + "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", + "dev": true, + "requires": { + "postcss": "^7.0.5" + } + }, + "postcss-modules-local-by-default": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz", + "integrity": "sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw==", + "dev": true, + "requires": { + "icss-utils": "^4.1.1", + "postcss": "^7.0.32", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-modules-scope": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz", + "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==", + "dev": true, + "requires": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0" + } + }, + "postcss-modules-values": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz", + "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==", + "dev": true, + "requires": { + "icss-utils": "^4.0.0", + "postcss": "^7.0.6" + } + }, + "postcss-selector-parser": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz", + "integrity": "sha512-gjMeXBempyInaBqpp8gODmwZ52WaYsVOsfr4L4lDQ7n3ncD6mEyySiDtgzCT+NYC0mmeOLvtsF8iaEf0YT6dBw==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1", + "util-deprecate": "^1.0.2" + } + }, + "postcss-value-parser": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", + "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "pretty-error": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.2.tgz", + "integrity": "sha512-EY5oDzmsX5wvuynAByrmY0P0hcp+QpnAKbJng2A2MPjVKXCxrDSUkzghVJ4ZGPIv+JC4gX8fPUWscC0RtjsWGw==", + "dev": true, + "requires": { + "lodash": "^4.17.20", + "renderkid": "^2.0.4" + } + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, + "proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "dev": true, + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "dependencies": { + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true + } + } + }, + "raw-loader": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz", + "integrity": "sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "dependencies": { + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "react": { + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz", + "integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2" + } + }, + "react-dom": { + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", + "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.19.1" + } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "react-router": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz", + "integrity": "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==", + "requires": { + "@babel/runtime": "^7.1.2", + "history": "^4.9.0", + "hoist-non-react-statics": "^3.1.0", + "loose-envify": "^1.3.1", + "mini-create-react-context": "^0.4.0", + "path-to-regexp": "^1.7.0", + "prop-types": "^15.6.2", + "react-is": "^16.6.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + } + }, + "react-router-dom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.2.0.tgz", + "integrity": "sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==", + "requires": { + "@babel/runtime": "^7.1.2", + "history": "^4.9.0", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.2", + "react-router": "5.2.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "recast": { + "version": "0.11.23", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.11.23.tgz", + "integrity": "sha1-RR/TAEqx5N+bTktmN2sqIZEkYtM=", + "dev": true, + "requires": { + "ast-types": "0.9.6", + "esprima": "~3.1.0", + "private": "~0.1.5", + "source-map": "~0.5.0" + }, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true + } + } + }, + "rechoir": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.0.tgz", + "integrity": "sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q==", + "dev": true, + "requires": { + "resolve": "^1.9.0" + } + }, + "regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "regenerate-unicode-properties": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", + "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", + "dev": true, + "requires": { + "regenerate": "^1.4.0" + } + }, + "regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" + }, + "regenerator-transform": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", + "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.8.4" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regexp.prototype.flags": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", + "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + }, + "regexpu-core": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz", + "integrity": "sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ==", + "dev": true, + "requires": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.2.0", + "regjsgen": "^0.5.1", + "regjsparser": "^0.6.4", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.2.0" + } + }, + "regjsgen": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", + "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==", + "dev": true + }, + "regjsparser": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.6.tgz", + "integrity": "sha512-jjyuCp+IEMIm3N1H1LLTJW1EISEJV9+5oHdEyrt43Pg9cDSb6rrLZei2cVWpl0xTjmmlpec/lEQGYgM7xfpGCQ==", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, + "relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", + "dev": true + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "renderkid": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.5.tgz", + "integrity": "sha512-ccqoLg+HLOHq1vdfYNm4TBeaCDIi1FLt3wGojTDSvdewUv65oTmI3cnT2E4hRjl1gzKZIPK+KZrXzlUYKnR+vQ==", + "dev": true, + "requires": { + "css-select": "^2.0.2", + "dom-converter": "^0.2", + "htmlparser2": "^3.10.1", + "lodash": "^4.17.20", + "strip-ansi": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "reselect": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.0.0.tgz", + "integrity": "sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA==", + "dev": true + }, + "resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "requires": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + } + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "resolve-pathname": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", + "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true + }, + "run-parallel": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", + "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==", + "dev": true + }, + "rxjs": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "scheduler": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", + "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + } + }, + "select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", + "dev": true + }, + "selfsigned": { + "version": "1.10.8", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.8.tgz", + "integrity": "sha512-2P4PtieJeEwVgTU9QEcwIRDQ/mXJLX8/+I3ur+Pg16nS8oNbrGxEso9NyYWy8NAmXiNl4dlAp5MwoNeCWzON4w==", + "dev": true, + "requires": { + "node-forge": "^0.10.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dev": true, + "requires": { + "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" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + } + } + }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dev": true, + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + }, + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "sockjs": { + "version": "0.3.21", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.21.tgz", + "integrity": "sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw==", + "dev": true, + "requires": { + "faye-websocket": "^0.11.3", + "uuid": "^3.4.0", + "websocket-driver": "^0.7.4" + } + }, + "sockjs-client": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.5.0.tgz", + "integrity": "sha512-8Dt3BDi4FYNrCFGTL/HtwVzkARrENdwOUf1ZoW/9p3M8lZdFT35jVdrHza+qgxuG9H3/shR4cuX/X9umUrjP8Q==", + "dev": true, + "requires": { + "debug": "^3.2.6", + "eventsource": "^1.0.7", + "faye-websocket": "^0.11.3", + "inherits": "^2.0.4", + "json3": "^3.3.3", + "url-parse": "^1.4.7" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "dev": true, + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + } + }, + "spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "string.prototype.matchall": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.3.tgz", + "integrity": "sha512-OBxYDA2ifZQ2e13cP82dWFMaCV9CGF8GzmN4fljBVw5O5wep0lu4gacm1OL6MjROoUnB8VbkWRThqkV2YFLNxw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "has-symbols": "^1.0.1", + "internal-slot": "^1.0.2", + "regexp.prototype.flags": "^1.3.0", + "side-channel": "^1.0.3" + } + }, + "string.prototype.trimend": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz", + "integrity": "sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + } + }, + "string.prototype.trimstart": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz", + "integrity": "sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "style-loader": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.3.0.tgz", + "integrity": "sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^2.7.0" + }, + "dependencies": { + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + } + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true + }, + "tar": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz", + "integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==", + "dev": true, + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "dependencies": { + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + } + } + }, + "terser": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.5.1.tgz", + "integrity": "sha512-6VGWZNVP2KTUcltUQJ25TtNjx/XgdDsBDKGt8nN0MpydU36LmbPPcMBd2kmtZNNGVVDLg44k7GKeHHj+4zPIBQ==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.19" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + } + } + }, + "terser-webpack-plugin": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.1.1.tgz", + "integrity": "sha512-5XNNXZiR8YO6X6KhSGXfY0QrGrCRlSwAEjIIrlRQR4W8nP69TaJUlh3bkuac6zzgspiGPfKEHcY295MMVExl5Q==", + "dev": true, + "requires": { + "jest-worker": "^26.6.2", + "p-limit": "^3.1.0", + "schema-utils": "^3.0.0", + "serialize-javascript": "^5.0.1", + "source-map": "^0.6.1", + "terser": "^5.5.1" + }, + "dependencies": { + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true + }, + "tiny-invariant": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz", + "integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==" + }, + "tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "tsutils": { + "version": "3.19.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.19.1.tgz", + "integrity": "sha512-GEdoBf5XI324lu7ycad7s6laADfnAqCw6wLGI+knxvw9vsIYBaJfYdmeCEG3FMMUiSm3OGgNb+m6utsWf5h9Vw==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typescript": { + "version": "3.9.7", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz", + "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==", + "dev": true + }, + "uglify-js": { + "version": "3.4.10", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz", + "integrity": "sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==", + "dev": true, + "requires": { + "commander": "~2.19.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "unicode-canonical-property-names-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", + "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", + "dev": true + }, + "unicode-match-property-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", + "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", + "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==", + "dev": true + }, + "unicode-property-aliases-ecmascript": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", + "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==", + "dev": true + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true + }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true + }, + "upper-case": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", + "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", + "dev": true + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "url-parse": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", + "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", + "dev": true, + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "use-clipboard-copy": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/use-clipboard-copy/-/use-clipboard-copy-0.1.2.tgz", + "integrity": "sha512-EkauxqyX+us4+Mfif/f61ew89EAOWIArqFpHR0jSG4SwwuDZzDAOeqO7gkK0vi+DQVADeB1RB3xqU3U0oOO3NQ==", + "requires": { + "clipboard-copy": "^3.0.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" + } + }, + "utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", + "dev": true + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + }, + "v8-compile-cache": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", + "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==", + "dev": true + }, + "value-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", + "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true + }, + "watchpack": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.1.0.tgz", + "integrity": "sha512-UjgD1mqjkG99+3lgG36at4wPnUXNvis2v1utwTgQ43C22c4LD71LsYMExdWXh4HZ+RmW+B0t1Vrg2GpXAkTOQw==", + "dev": true, + "requires": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + } + }, + "wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "requires": { + "minimalistic-assert": "^1.0.0" + } + }, + "webpack": { + "version": "5.12.3", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.12.3.tgz", + "integrity": "sha512-7tiQmcTnKhZwbf7X7sEfXe0pgkGjUZjT6JfYkZHvvIb4/ZsXl1rJu5PxsJoN7W3v5sNSP/8TgBoiOdDqVdvK5w==", + "dev": true, + "requires": { + "@types/eslint-scope": "^3.7.0", + "@types/estree": "^0.0.45", + "@webassemblyjs/ast": "1.11.0", + "@webassemblyjs/wasm-edit": "1.11.0", + "@webassemblyjs/wasm-parser": "1.11.0", + "acorn": "^8.0.4", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.3.1", + "eslint-scope": "^5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.4", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "pkg-dir": "^5.0.0", + "schema-utils": "^3.0.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.1", + "watchpack": "^2.0.0", + "webpack-sources": "^2.1.1" + }, + "dependencies": { + "acorn": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.0.4.tgz", + "integrity": "sha512-XNP0PqF1XD19ZlLKvB7cMmnZswW4C/03pRHgirB30uSJTaS3A3V1/P4sS3HPvFmjoriPCJQs+JDSbm4bL1TxGQ==", + "dev": true + }, + "enhanced-resolve": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.5.0.tgz", + "integrity": "sha512-b4a6BasBCoLzri4MdaeOlDMpls2oioI28CF17csMiav9dq46yvQaKPFNUrCHB6VqQokBDG2VIEEL81jMiQ6Wtw==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "pkg-dir": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", + "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", + "dev": true, + "requires": { + "find-up": "^5.0.0" + } + }, + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", + "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "tapable": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.0.tgz", + "integrity": "sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw==", + "dev": true + }, + "webpack-sources": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.2.0.tgz", + "integrity": "sha512-bQsA24JLwcnWGArOKUxYKhX3Mz/nK1Xf6hxullKERyktjNMC4x8koOeaDNTA2fEJ09BdWLbM/iTW0ithREUP0w==", + "dev": true, + "requires": { + "source-list-map": "^2.0.1", + "source-map": "^0.6.1" + } + } + } + }, + "webpack-cli": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.3.1.tgz", + "integrity": "sha512-/F4+9QNZM/qKzzL9/06Am8NXIkGV+/NqQ62Dx7DSqudxxpAgBqYn6V7+zp+0Y7JuWksKUbczRY3wMTd+7Uj6OA==", + "dev": true, + "requires": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/info": "^1.2.1", + "@webpack-cli/serve": "^1.2.1", + "colorette": "^1.2.1", + "commander": "^6.2.0", + "enquirer": "^2.3.6", + "execa": "^5.0.0", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^2.2.0", + "rechoir": "^0.7.0", + "v8-compile-cache": "^2.2.0", + "webpack-merge": "^4.2.2" + }, + "dependencies": { + "commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "execa": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", + "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "get-stream": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz", + "integrity": "sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==", + "dev": true + }, + "import-local": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", + "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", + "dev": true, + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + } + }, + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "dev": true + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "requires": { + "resolve-from": "^5.0.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "webpack-merge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.2.tgz", + "integrity": "sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g==", + "dev": true, + "requires": { + "lodash": "^4.17.15" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "webpack-dev-middleware": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz", + "integrity": "sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ==", + "dev": true, + "requires": { + "memory-fs": "^0.4.1", + "mime": "^2.4.4", + "mkdirp": "^0.5.1", + "range-parser": "^1.2.1", + "webpack-log": "^2.0.0" + }, + "dependencies": { + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "mime": { + "version": "2.4.7", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.7.tgz", + "integrity": "sha512-dhNd1uA2u397uQk3Nv5LM4lm93WYDUXFn3Fu291FJerns4jyTudqhIWe4W04YLy7Uk1tm1Ore04NpjRvQp/NPA==", + "dev": true + }, + "webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "dev": true, + "requires": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + } + } + } + }, + "webpack-dev-server": { + "version": "3.11.1", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.1.tgz", + "integrity": "sha512-u4R3mRzZkbxQVa+MBWi2uVpB5W59H3ekZAJsQlKUTdl7Elcah2EhygTPLmeFXybQkf9i2+L0kn7ik9SnXa6ihQ==", + "dev": true, + "requires": { + "ansi-html": "0.0.7", + "bonjour": "^3.5.0", + "chokidar": "^2.1.8", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", + "debug": "^4.1.1", + "del": "^4.1.1", + "express": "^4.17.1", + "html-entities": "^1.3.1", + "http-proxy-middleware": "0.19.1", + "import-local": "^2.0.0", + "internal-ip": "^4.3.0", + "ip": "^1.1.5", + "is-absolute-url": "^3.0.3", + "killable": "^1.0.1", + "loglevel": "^1.6.8", + "opn": "^5.5.0", + "p-retry": "^3.0.1", + "portfinder": "^1.0.26", + "schema-utils": "^1.0.0", + "selfsigned": "^1.10.8", + "semver": "^6.3.0", + "serve-index": "^1.9.1", + "sockjs": "^0.3.21", + "sockjs-client": "^1.5.0", + "spdy": "^4.0.2", + "strip-ansi": "^3.0.1", + "supports-color": "^6.1.0", + "url": "^0.11.0", + "webpack-dev-middleware": "^3.7.2", + "webpack-log": "^2.0.0", + "ws": "^6.2.1", + "yargs": "^13.3.2" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "dev": true, + "requires": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + } + } + } + }, + "webpack-log": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-1.2.0.tgz", + "integrity": "sha512-U9AnICnu50HXtiqiDxuli5gLB5PGBo7VvcHx36jRZHwK4vzOYLbImqT4lwWwoMHdQWwEKw736fCHEekokTEKHA==", + "dev": true, + "requires": { + "chalk": "^2.1.0", + "log-symbols": "^2.1.0", + "loglevelnext": "^1.0.1", + "uuid": "^3.1.0" + } + }, + "webpack-merge": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.7.3.tgz", + "integrity": "sha512-6/JUQv0ELQ1igjGDzHkXbVDRxkfA57Zw7PfiupdLFJYrgFqY5ZP8xxbpp2lU3EPwYx89ht5Z/aDkD40hFCm5AA==", + "dev": true, + "requires": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + } + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "requires": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "wildcard": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", + "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", + "dev": true + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, + "ws": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", + "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + }, + "y18n": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", + "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + } + } +} diff --git a/utilities/cloudharness_utilities/application-templates/webapp/frontend/package.json b/utilities/cloudharness_utilities/application-templates/webapp/frontend/package.json new file mode 100644 index 00000000..58a41207 --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/webapp/frontend/package.json @@ -0,0 +1,58 @@ +{ + "name": "__APP_NAME__", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "prebuild": "eslint . --color", + "build": "webpack --config webpack.config.js", + "build-dev": "webpack --config webpack.config.js --env mode=development", + "prestart": "eslint . --color --fix", + "start": "webpack serve --progress --env DOMAIN=http://localhost:5000 --config webpack.config.dev.js", + "start:dev": "webpack serve --progress --env.DOMAIN=https://__APP_NAME__.cloudharness.metacell.us --config webpack.config.dev.js", + "start:minikube": "webpack serve --progress --env DOMAIN=http://__APP_NAME__.cloudharness.local --config webpack.config.dev.js" + }, + "author": "", + "license": "ISC", + "dependencies": { + "axios": "^0.21.1", + "react": "^16.12.0", + "react-dom": "^16.12.0", + "react-router": "^5.0.0", + "react-router-dom": "^5.0.0", + "use-clipboard-copy": "^0.1.2" + }, + "devDependencies": { + "@babel/core": "^7.8.3", + "@babel/plugin-proposal-class-properties": "^7.8.3", + "@babel/preset-env": "^7.8.3", + "@babel/preset-react": "^7.8.3", + "awesome-typescript-loader": "^5.2.1", + "babel-eslint": "^10.1.0", + "babel-loader": "^8.0.6", + "babel-plugin-module-resolver": "^4.0.0", + "babel-preset-minify": "^0.5.1", + "clean-webpack-plugin": "^3.0.0", + "compression-webpack-plugin": "^7.1.2", + "copy-webpack-plugin": "^6.2.1", + "css-loader": "^3.4.2", + "eslint": "5.16.0", + "eslint-plugin-jest": "^23.8.2", + "eslint-plugin-react": "^7.19.0", + "eslint-plugin-react-hooks": "^3.0.0", + "file-loader": "^5.0.2", + "html-loader": "^0.5.5", + "html-webpack-plugin": "^4.5.1", + "less": "^3.10.3", + "less-loader": "^5.0.0", + "less-vars-to-js": "^1.3.0", + "raw-loader": "^4.0.2", + "style-loader": "^1.1.3", + "typescript": "^3.9.3", + "webpack": "^5.0.0", + "webpack-cli": "^4.3.1", + "webpack-dev-server": "^3.11.1", + "webpack-merge": "^5.0.0" + } +} diff --git a/utilities/cloudharness_utilities/application-templates/webapp/frontend/src/App.tsx b/utilities/cloudharness_utilities/application-templates/webapp/frontend/src/App.tsx new file mode 100644 index 00000000..931ea6a6 --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/webapp/frontend/src/App.tsx @@ -0,0 +1,16 @@ +import React from 'react'; +import './styles/style.less'; + +import RestTest from './components/RestTest'; + + +const Main = () => ( + <> + +

Sample React application is working!

+ +

See api documentation here

+ +); + +export default Main; \ No newline at end of file diff --git a/utilities/cloudharness_utilities/application-templates/webapp/frontend/src/assets/icon.png b/utilities/cloudharness_utilities/application-templates/webapp/frontend/src/assets/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..1966e6ddade324846b39edd3aad248e7c61deaef GIT binary patch literal 35505 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 h { + const [result, setResult] = useState(null); + useEffect(() => { + test.ping().then(r => setResult(r)); + }, []); + + + return result &&

Backend answered: { result.data }

+} + +export default RestTest; \ No newline at end of file diff --git a/utilities/cloudharness_utilities/application-templates/webapp/frontend/src/index.ejs b/utilities/cloudharness_utilities/application-templates/webapp/frontend/src/index.ejs new file mode 100644 index 00000000..97d529ad --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/webapp/frontend/src/index.ejs @@ -0,0 +1,10 @@ + + + + + __APP_NAME__ + + +
+ + \ No newline at end of file diff --git a/utilities/cloudharness_utilities/application-templates/webapp/frontend/src/index.tsx b/utilities/cloudharness_utilities/application-templates/webapp/frontend/src/index.tsx new file mode 100644 index 00000000..ae31e413 --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/webapp/frontend/src/index.tsx @@ -0,0 +1,6 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; + +import App from './App'; + +ReactDOM.render(, document.getElementById('root')); diff --git a/utilities/cloudharness_utilities/application-templates/webapp/frontend/src/styles/style.less b/utilities/cloudharness_utilities/application-templates/webapp/frontend/src/styles/style.less new file mode 100644 index 00000000..b1bece6a --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/webapp/frontend/src/styles/style.less @@ -0,0 +1,4 @@ +body { + text-align: center; + background-color: '#eeeeee'; +} \ No newline at end of file diff --git a/utilities/cloudharness_utilities/application-templates/webapp/frontend/src/utils/history.js b/utilities/cloudharness_utilities/application-templates/webapp/frontend/src/utils/history.js new file mode 100644 index 00000000..7bef5c97 --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/webapp/frontend/src/utils/history.js @@ -0,0 +1,2 @@ +import { createBrowserHistory } from "history"; +export default createBrowserHistory(); \ No newline at end of file diff --git a/utilities/cloudharness_utilities/application-templates/webapp/frontend/tsconfig.json b/utilities/cloudharness_utilities/application-templates/webapp/frontend/tsconfig.json new file mode 100755 index 00000000..21ec6c41 --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/webapp/frontend/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "outDir": "./dist/", + "sourceMap": true, + "noImplicitAny": false, + "module": "commonjs", + "target": "es2017", + "stripInternal":true, + "skipLibCheck": true, + "alwaysStrict":false, + "forceConsistentCasingInFileNames": true, + "noImplicitReturns": false, + "strict": false, + "noUnusedLocals": false, + "jsx": "react", + "types": [], + "esModuleInterop": true + }, + "exclude": [ + "node_modules" + ] +} \ No newline at end of file diff --git a/utilities/cloudharness_utilities/application-templates/webapp/frontend/webpack.config.dev.js b/utilities/cloudharness_utilities/application-templates/webapp/frontend/webpack.config.dev.js new file mode 100644 index 00000000..ea3e8266 --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/webapp/frontend/webpack.config.dev.js @@ -0,0 +1,45 @@ +const { merge } = require('webpack-merge'); +const common = require('./webpack.config.js'); + +var path = require('path'); + +const PORT = 9000; + + +module.exports = env => { + + const theDomain = env && env.DOMAIN ? env.DOMAIN : 'localhost:5000'; + + console.log('Dev server address: ', theDomain); + + const proxyTarget = theDomain; + const replaceHost = (uri, appName) => (uri.includes("__APP_NAME__") && uri.replace("__APP_NAME__", appName + '.' + theDomain)) || uri; + if (!env.port) { + env.devPort = PORT; + } + + + const devServer = { + contentBase: path.join(__dirname, 'dist'), + compress: true, + port: Number(env.devPort), + disableHostCheck: true, + historyApiFallback: true, + proxy: { + '/api/': { + target: replaceHost( proxyTarget, '__APP_NAME__'), + secure: false, + changeOrigin: true, + } + }, + }; + + return merge( + common(env), + { + mode: 'development', + devtool: 'source-map', + devServer, + } + ) +}; diff --git a/utilities/cloudharness_utilities/application-templates/webapp/frontend/webpack.config.js b/utilities/cloudharness_utilities/application-templates/webapp/frontend/webpack.config.js new file mode 100644 index 00000000..b2dca762 --- /dev/null +++ b/utilities/cloudharness_utilities/application-templates/webapp/frontend/webpack.config.js @@ -0,0 +1,110 @@ +const path = require('path'); +const HtmlWebpackPlugin = require('html-webpack-plugin'); +const CompressionPlugin = require('compression-webpack-plugin'); +const { CleanWebpackPlugin } = require('clean-webpack-plugin'); +const CopyWebpackPlugin = require('copy-webpack-plugin'); + +const copyPaths = [ + { from: path.resolve(__dirname, "src/assets"), to: 'assets' }, +]; + +module.exports = function webpacking(envVariables) { + let env = envVariables; + if (!env) { + env = {}; + } + if (!env.mode) { + env.mode = 'production'; + } + + + console.log('####################'); + console.log('####################'); + console.log('BUILD bundle with parameters:'); + console.log( env); + console.log('####################'); + console.log('####################'); + + const { mode } = env; + const devtool = env.mode === 'source-map'; + + + const output = { + path: path.resolve(__dirname, 'dist'), + filename: '[name].[contenthash].js' + }; + + const module = { + rules: [ + { + test: /\.(js|jsx)$/, + exclude: /node_modules/, + loader: 'babel-loader' + }, + { + test: /\.ts|tsx?$/, + loader: "awesome-typescript-loader" + }, + { + test: /\.(css)$/, + use: [ + { + loader: "style-loader", + }, + { + loader: "css-loader", + }], + }, + { + test: /\.less$/, + use: [ + { + loader: "style-loader", + }, + { + loader: "css-loader", + }, + { + loader: "less-loader", + options: { + lessOptions: { + strictMath: true, + }, + }, + }, + ], + }, + { + test: /\.(png|jpg|gif|eot|woff|woff2|svg|ttf)$/, + loader: 'file-loader' + }, + + ] + }; + + const resolve = { + extensions: ['*', '.js', '.json', '.ts', '.tsx', '.jsx'], + symlinks: false + }; + + + + const plugins = [ + new CleanWebpackPlugin(), + new CopyWebpackPlugin({ patterns: copyPaths }), + new CompressionPlugin(), + new HtmlWebpackPlugin({ + template: 'src/index.ejs', + favicon: path.join(__dirname, 'src/assets/icon.png') + }) + ]; + + return { + mode, + devtool, + output, + module, + resolve, + plugins + }; +}; diff --git a/utilities/cloudharness_utilities/build.py b/utilities/cloudharness_utilities/build.py index da1fdde9..944230ae 100644 --- a/utilities/cloudharness_utilities/build.py +++ b/utilities/cloudharness_utilities/build.py @@ -1,15 +1,17 @@ import os +import sys import logging import tempfile from docker import from_env as DockerClient from .utils import find_dockerfiles_paths, app_name_from_path, merge_configuration_directories -from .constants import NODE_BUILD_IMAGE, APPS_PATH, STATIC_IMAGES_PATH, BASE_IMAGES_PATH +from .constants import NODE_BUILD_IMAGE, APPS_PATH, STATIC_IMAGES_PATH, BASE_IMAGES_PATH, EXCLUDE_PATHS + class Builder: - def __init__(self, root_paths, include, tag, namespace, domain, registry='', interactive=False, + def __init__(self, root_paths, include, tag, namespace, domain, registry='', interactive=False, exclude=tuple()): self.included = include or [] self.tag = tag @@ -43,8 +45,8 @@ def push(self, image_repository): # filter the images to build - def should_build_image(self, image_path) -> bool: - if image_path in self.exclude: + def should_build_image(self, image_path, ignore_include=False) -> bool: + if any(excluded_path in image_path for excluded_path in (EXCLUDE_PATHS + list(self.exclude))): return False if not self.included: if self.interactive: @@ -52,7 +54,7 @@ def should_build_image(self, image_path) -> bool: return answer.upper() != 'N' return True - if any(inc in image_path for inc in self.included): + if ignore_include or any(f"/{inc}/" in image_path or image_path.endswith(f"/{inc}") for inc in self.included): return True logging.info("Skipping build for image %s", image_path) return False @@ -62,23 +64,22 @@ def run(self): logging.info('Start building docker images') for rpath in self.root_paths: logging.info('Building from root directory %s', rpath) - self.find_and_build_under_path(BASE_IMAGES_PATH, rpath, rpath) - self.find_and_build_under_path(STATIC_IMAGES_PATH, None, rpath) + self.find_and_build_under_path(BASE_IMAGES_PATH, rpath, rpath, ignore_include=True) + self.find_and_build_under_path(STATIC_IMAGES_PATH, None, rpath, ignore_include=True) self.find_and_build_under_path(APPS_PATH, None, rpath) - def find_and_build_under_path(self, base_path, context_path=None, root_path=None): + def find_and_build_under_path(self, base_path, context_path=None, root_path=None, ignore_include=False): abs_base_path = os.path.join(root_path, base_path) docker_files = (path for path in find_dockerfiles_paths(abs_base_path) if - self.should_build_image(path)) + self.should_build_image(path, ignore_include)) for dockerfile_path in docker_files: dockerfile_rel_path = "" if not context_path else os.path.relpath(dockerfile_path, start=context_path) # extract image name image_name = app_name_from_path(os.path.relpath(dockerfile_path, start=abs_base_path)) - if self.should_build_image(os.path.relpath(dockerfile_path, start=abs_base_path)): - self.build_image(image_name, dockerfile_rel_path, - context_path=context_path if context_path else dockerfile_path) + self.build_image(image_name, dockerfile_rel_path, + context_path=context_path if context_path else dockerfile_path) def build_under_path(self, dpath): """ Uses docker sdk to build a docker images from path information """ @@ -88,12 +89,12 @@ def build_under_path(self, dpath): dockerfile_path = dpath['abs_path'] self.build_image(image_name, dockerfile_rel_path, - context_path=context_path if context_path else dockerfile_path) - + context_path=context_path if context_path else dockerfile_path) def build_image(self, image_name, dockerfile_rel_path, context_path=None): - registry = "" if not self.registry else self.registry.strip('/') + '/' # make sure the registry ends with only one single / + registry = "" if not self.registry else self.registry.strip( + '/') + '/' # make sure the registry ends with only one single / # build image image_tag = f'{registry}{image_name}:{self.tag}' if self.tag else image_name @@ -103,13 +104,22 @@ def build_image(self, image_name, dockerfile_rel_path, context_path=None): logging.info(f'\n{80 * "#"}\nBuilding {image_tag} \n{80 * "#"}\n') logging.info("Build args: " + ",".join(key + ':' + value for key, value in buildargs.items())) - image, response = self.client.images.build(path=context_path, - tag=image_tag, - buildargs=buildargs, - dockerfile=os.path.join(dockerfile_rel_path, - "Dockerfile") if dockerfile_rel_path else None - ) + try: + image, response = self.client.images.build(path=context_path, + tag=image_tag, + buildargs=buildargs, + dockerfile=os.path.join(dockerfile_rel_path, + "Dockerfile") if dockerfile_rel_path else None + + ) + except Exception as e: + for line in e.build_log: + if 'stream' in line and line['stream'] != '\n': + logging.info(line['stream'].replace('\n', ' ').replace('\r', '')) + logging.error("Build failed with message:\n%s", ",".join(e.args)) + + sys.exit(1) # log stream for line in response: if 'stream' in line and line['stream'] != '\n': @@ -117,8 +127,7 @@ def build_image(self, image_name, dockerfile_rel_path, context_path=None): if self.registry: self.push(image_tag) - - def log_merging_operation(self, dpaths:[dict]) -> None: + def log_merging_operation(self, dpaths: [dict]) -> None: logging_message = f"\n\nFound multiple dockerfiles for the next image ({dpaths[0]['name']}):\n\n" for dpath in dpaths: logging_message += f"{dpath['abs_path']}\n" diff --git a/utilities/cloudharness_utilities/codefresh.py b/utilities/cloudharness_utilities/codefresh.py index 5d0b29eb..4111a70a 100644 --- a/utilities/cloudharness_utilities/codefresh.py +++ b/utilities/cloudharness_utilities/codefresh.py @@ -1,10 +1,12 @@ import os import oyaml as yaml +import yaml.representer + import logging -from .constants import HERE, BUILD_STEP_BASE, BUILD_STEP_STATIC, BUILD_STEP_PARALLEL, BUILD_STEP_INSTALL, \ - CODEFRESH_PATH, CODEFRESH_BUILD_PATH, \ - CODEFRESH_TEMPLATE_PATH, APPS_PATH, STATIC_IMAGES_PATH, BASE_IMAGES_PATH, DEPLOYMENT_PATH +from .constants import HERE, CF_BUILD_STEP_BASE, CF_BUILD_STEP_STATIC, CF_BUILD_STEP_PARALLEL, CF_STEP_PUBLISH, \ + CODEFRESH_PATH, CF_BUILD_PATH, CF_TEMPLATE_PUBLISH_PATH, DEPLOYMENT_CONFIGURATION_PATH, \ + CF_TEMPLATE_PATH, APPS_PATH, STATIC_IMAGES_PATH, BASE_IMAGES_PATH, DEPLOYMENT_PATH, EXCLUDE_PATHS from .helm import collect_helm_values from .utils import find_dockerfiles_paths, app_name_from_path, \ get_image_name, get_template, merge_to_yaml_file, dict_merge @@ -14,7 +16,20 @@ CLOUD_HARNESS_PATH = "cloud-harness" -def create_codefresh_deployment_scripts(root_paths, codefresh_path=CODEFRESH_PATH, include=()): +# Codefresh variables may need quotes: adjust yaml dump accordingly +def literal_presenter(dumper, data): + if isinstance(data, str) and "\n" in data: + return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='|') + if isinstance(data, str) and data.startswith('${{'): + return dumper.represent_scalar('tag:yaml.org,2002:str', data, style="'") + return dumper.represent_scalar('tag:yaml.org,2002:str', data) + + +yaml.add_representer(str, literal_presenter) + + +def create_codefresh_deployment_scripts(root_paths, out_filename=CODEFRESH_PATH, include=(), exclude=(), + template_name=CF_TEMPLATE_PATH): """ Entry point to create deployment scripts for codefresh: codefresh.yaml and helm chart """ @@ -22,46 +37,76 @@ def create_codefresh_deployment_scripts(root_paths, codefresh_path=CODEFRESH_PAT if include: logging.info('Including the following subpaths to the build: %s.', ', '.join(include)) - codefresh = get_template(os.path.join(HERE, CODEFRESH_TEMPLATE_PATH)) + if exclude: + logging.info('Excluding the following subpaths to the build: %s.', ', '.join(exclude)) + + codefresh = get_template(os.path.join(HERE, template_name), True) - codefresh['steps'][BUILD_STEP_BASE]['steps'] = {} - codefresh['steps'][BUILD_STEP_STATIC]['steps'] = {} - codefresh['steps'][BUILD_STEP_PARALLEL]['steps'] = {} + if not codefresh: + if template_name != CF_TEMPLATE_PATH: + logging.warning("Template file %s not found", template_name) + if os.path.exists(os.path.join(HERE, CF_TEMPLATE_PATH)): + logging.info("Loading legacy template %s", CF_TEMPLATE_PATH) + codefresh = get_template(os.path.join(HERE, CF_TEMPLATE_PATH), True) + return + + if CF_BUILD_STEP_BASE in codefresh['steps']: + codefresh['steps'][CF_BUILD_STEP_BASE]['steps'] = {} + codefresh['steps'][CF_BUILD_STEP_STATIC]['steps'] = {} + codefresh['steps'][CF_BUILD_STEP_PARALLEL]['steps'] = {} + if CF_STEP_PUBLISH in codefresh['steps']: + codefresh['steps'][CF_STEP_PUBLISH]['steps'] = {} for root_path in root_paths: - template_path = os.path.join(root_path, CODEFRESH_TEMPLATE_PATH) + template_path = os.path.join(root_path, DEPLOYMENT_CONFIGURATION_PATH, template_name) if os.path.exists(template_path): - tpl = get_template(template_path) - del tpl['steps'][BUILD_STEP_BASE] - del tpl['steps'][BUILD_STEP_STATIC] - del tpl['steps'][BUILD_STEP_PARALLEL] + tpl = get_template(template_path, True) + if CF_BUILD_STEP_BASE in codefresh['steps']: + del tpl['steps'][CF_BUILD_STEP_BASE] + if CF_BUILD_STEP_STATIC in codefresh['steps']: + del tpl['steps'][CF_BUILD_STEP_STATIC] + if CF_BUILD_STEP_PARALLEL in codefresh['steps']: + del tpl['steps'][CF_BUILD_STEP_PARALLEL] + if CF_STEP_PUBLISH in codefresh['steps']: + del tpl['steps'][CF_STEP_PUBLISH] codefresh = dict_merge(codefresh, tpl) - def codefresh_build_step_from_base_path(base_path, build_step, fixed_context=None): + def codefresh_build_step_from_base_path(base_path, build_step, fixed_context=None, include=include): abs_base_path = os.path.join(os.getcwd(), base_path) for dockerfile_path in find_dockerfiles_paths(abs_base_path): app_relative_to_root = os.path.relpath(dockerfile_path, '.') app_relative_to_base = os.path.relpath(dockerfile_path, abs_base_path) app_name = app_name_from_path(app_relative_to_base) - if include and not any(inc in dockerfile_path for inc in include): + if include and not any( + f"/{inc}/" in dockerfile_path or dockerfile_path.endswith(f"/{inc}") for inc in include): continue - build = codefresh_app_build_spec( - app_name=app_name, - app_context_path=os.path.relpath(fixed_context, '.') if fixed_context else app_relative_to_root, - dockerfile_path=os.path.join(os.path.relpath(dockerfile_path, fixed_context) if fixed_context else '', - "Dockerfile")) - codefresh['steps'][build_step]['steps'][app_name] = build - - codefresh_build_step_from_base_path(os.path.join(root_path, BASE_IMAGES_PATH), BUILD_STEP_BASE, - fixed_context=root_path) - codefresh_build_step_from_base_path(os.path.join(root_path, STATIC_IMAGES_PATH), BUILD_STEP_STATIC) - codefresh_build_step_from_base_path(os.path.join(root_path, APPS_PATH), BUILD_STEP_PARALLEL) - + if any(inc in dockerfile_path for inc in (list(exclude) + EXCLUDE_PATHS)): + continue + build = None + if CF_BUILD_STEP_BASE in codefresh['steps']: + build = codefresh_app_build_spec( + app_name=app_name, + app_context_path=os.path.relpath(fixed_context, '.') if fixed_context else app_relative_to_root, + dockerfile_path=os.path.join( + os.path.relpath(dockerfile_path, fixed_context) if fixed_context else '', + "Dockerfile")) + codefresh['steps'][build_step]['steps'][app_name] = build + if CF_STEP_PUBLISH in codefresh['steps']: + codefresh['steps'][CF_STEP_PUBLISH]['steps']['publish_' + app_name] = codefresh_app_publish_spec( + app_name=app_name, build_tag=build and build['tag']) + + codefresh_build_step_from_base_path(os.path.join(root_path, BASE_IMAGES_PATH), CF_BUILD_STEP_BASE, + fixed_context=root_path, include=None) + codefresh_build_step_from_base_path(os.path.join(root_path, STATIC_IMAGES_PATH), CF_BUILD_STEP_STATIC, + include=None) + codefresh_build_step_from_base_path(os.path.join(root_path, APPS_PATH), CF_BUILD_STEP_PARALLEL) + + # Remove useless steps codefresh['steps'] = {k: step for k, step in codefresh['steps'].items() if 'type' not in step or step['type'] != 'parallel' or ( step['steps'] if 'steps' in step else [])} - codefresh_abs_path = os.path.join(os.getcwd(), DEPLOYMENT_PATH, codefresh_path) + codefresh_abs_path = os.path.join(os.getcwd(), DEPLOYMENT_PATH, out_filename) codefresh_dir = os.path.dirname(codefresh_abs_path) if not os.path.exists(codefresh_dir): os.makedirs(codefresh_dir) @@ -69,24 +114,45 @@ def codefresh_build_step_from_base_path(base_path, build_step, fixed_context=Non yaml.dump(codefresh, f) -def codefresh_build_spec(**kwargs): +def codefresh_template_spec(template_path, **kwargs): """ Create Codefresh build specification :return: """ - build = get_template(CODEFRESH_BUILD_PATH) + build = get_template(template_path, True) build.update(kwargs) return build +def codefresh_app_publish_spec(app_name, build_tag): + title = app_name.capitalize().replace('-', ' ').replace('/', ' ').replace('.', ' ').strip() + + step_spec = codefresh_template_spec( + template_path=CF_TEMPLATE_PUBLISH_PATH, + candidate="${{REGISTRY}}/%s:%s" % (get_image_name(app_name), build_tag or '${{DEPLOYMENT_TAG}}'), + title=title, + ) + if not build_tag: + # if not build tag we are reusing old images and deploying on a production env + step_spec['tags'].append('latest') + return step_spec + + +def app_specific_tag_variable(app_name): + return "${{ %s }}_${{DEPLOYMENT_PUBLISH_TAG}}" % app_name.replace('-', '_').upper() + + def codefresh_app_build_spec(app_name, app_context_path, dockerfile_path="Dockerfile"): logging.info('Generating build script for ' + app_name) title = app_name.capitalize().replace('-', ' ').replace('/', ' ').replace('.', ' ').strip() - build = codefresh_build_spec(image_name=get_image_name(app_name), title=title, - working_directory='./' + app_context_path, - dockerfile=dockerfile_path) + build = codefresh_template_spec( + template_path=CF_BUILD_PATH, + image_name=get_image_name(app_name), + title=title, + working_directory='./' + app_context_path, + dockerfile=dockerfile_path) specific_build_template_path = os.path.join(app_context_path, 'build.yaml') if os.path.exists(specific_build_template_path): diff --git a/utilities/cloudharness_utilities/constants.py b/utilities/cloudharness_utilities/constants.py index 7b29ba8c..cc274879 100644 --- a/utilities/cloudharness_utilities/constants.py +++ b/utilities/cloudharness_utilities/constants.py @@ -5,6 +5,8 @@ HERE = os.path.dirname(os.path.realpath(__file__)).replace(os.path.sep, '/') ROOT = os.path.dirname(HERE) +APPLICATION_TEMPLATE_PATH = 'application-templates' + HELM_PATH = "helm" HELM_CHART_PATH = HELM_PATH @@ -15,23 +17,23 @@ APPS_PATH = 'applications' DEPLOYMENT_PATH = 'deployment' CODEFRESH_PATH = 'codefresh/codefresh.yaml' +EXCLUDE_PATHS = ['node_modules', '.git', '.tox'] DEPLOYMENT_CONFIGURATION_PATH = 'deployment-configuration' -CODEFRESH_BUILD_PATH = f'{DEPLOYMENT_CONFIGURATION_PATH}/codefresh-build-template.yaml' -CODEFRESH_TEMPLATE_PATH = f'{DEPLOYMENT_CONFIGURATION_PATH}/codefresh-template.yaml' -CODEFRESH_REGISTRY = "r.cfcr.io/tarelli" +CF_BUILD_PATH = f'{DEPLOYMENT_CONFIGURATION_PATH}/codefresh-build-template.yaml' +CF_TEMPLATE_PATH = f'{DEPLOYMENT_CONFIGURATION_PATH}/codefresh-template.yaml' +CF_TEMPLATE_PUBLISH_PATH = f'{DEPLOYMENT_CONFIGURATION_PATH}/codefresh-publish-template.yaml' VALUES_MANUAL_PATH = 'values.yaml' VALUE_TEMPLATE_PATH = f'{DEPLOYMENT_CONFIGURATION_PATH}/value-template.yaml' -CH_BASE_IMAGES = {'cloudharness-base': 'python:3.7-alpine', 'cloudharness-base-debian': 'python:3'} - +CH_BASE_IMAGES = {'cloudharness-base': 'python:3.7-alpine', 'cloudharness-base-debian': 'python:3.7'} -BUILD_STEP_BASE = 'build_base_images' -BUILD_STEP_STATIC = 'build_static_images' -BUILD_STEP_PARALLEL = 'build_application_images' -BUILD_STEP_INSTALL = 'deployment' +CF_BUILD_STEP_BASE = 'build_base_images' +CF_BUILD_STEP_STATIC = 'build_static_images' +CF_BUILD_STEP_PARALLEL = 'build_application_images' +CF_STEP_INSTALL = 'deployment' +CF_STEP_PUBLISH = 'publish' BUILD_FILENAMES = ('node_modules',) - diff --git a/utilities/cloudharness_utilities/deployment-configuration/README.md b/utilities/cloudharness_utilities/deployment-configuration/README.md index ff3d1c51..24fd58e8 100644 --- a/utilities/cloudharness_utilities/deployment-configuration/README.md +++ b/utilities/cloudharness_utilities/deployment-configuration/README.md @@ -1,8 +1,38 @@ # Default deployment templates + Templates used to personalize the automatic infrastructure definition. -Those files are used by the script `insfrastructure-generate.py` -- `values-template.yaml`: base for `helm/values.yaml`. Modify this file to add values related to new infrastructure elements not defined as a CloudHarness application (e.g. a new database) -- `value-template.yaml`: base for cloudharness application configuration inside `values.yaml`. Prefer adding a custom `values.yaml` to your application over changing this file. -- `codefresh-template.yaml`: base for `codefresh/codefresh.yaml`. Modify this file if you want to change the build steps inside codefresh +Those files are used by the script `harness-deployment` script. + +- `values-template.yaml`: base for `helm/values.yaml`. Modify this file to add values related to new infrastructure + elements not defined as a CloudHarness application (e.g. a new database) +- `value-template.yaml`: base for cloudharness application configuration inside `values.yaml`. Prefer adding a + custom `values.yaml` to your application over changing this file. +- `codefresh-template-[dev|prod].yaml`: base for `codefresh/codefresh-[dev|prod].yaml`. Modify this file if you want to + change the build steps inside codefresh - `codefresh-build-template.yaml`: base for a single build entry in `codefresh.yaml` +- `codefresh-publish-template.yaml`: base for a single publish (image tagging) entry in `codefresh.yaml` + +## Generating HELM Chart documentation + +We use [helm-docs](https://github.com/norwoodj/helm-docs) to generate a markdown file containing a table of all +available parameters. + +Please follow their [installation instruction](https://github.com/norwoodj/helm-docs#installation), either use `brew` on MacOS or +install from source. If you install from source, `go` is required. + +`helm-docs` is able to parse yaml comments, but only if they are prefixed with `--`: + +```yaml +registry: + # -- The docker registry. + name: "localhost:5000" +``` + +To generate HELM chart documentation run: + +````bash +helm-docs --dry-run > docs.md +```` + +As a final step, update the content in the respective Cloud Harness wiki page. \ No newline at end of file diff --git a/utilities/cloudharness_utilities/deployment-configuration/codefresh-build-template.yaml b/utilities/cloudharness_utilities/deployment-configuration/codefresh-build-template.yaml index e0af336c..d5b04b94 100644 --- a/utilities/cloudharness_utilities/deployment-configuration/codefresh-build-template.yaml +++ b/utilities/cloudharness_utilities/deployment-configuration/codefresh-build-template.yaml @@ -1,9 +1,10 @@ type: build stage: build -tag: '${{CF_REVISION}}' +tag: '${{CF_BUILD_ID}}' dockerfile: Dockerfile +registry: '${{CODEFRESH_REGISTRY}}' build_arguments: - - REGISTRY=${{REGISTRY}} - - TAG=${{CF_REVISION}} + - REGISTRY=${{REGISTRY}}/ + - TAG=${{CF_BUILD_ID}} - NAMESPACE=${{NAMESPACE}} - DOMAIN=${{DOMAIN}} diff --git a/utilities/cloudharness_utilities/deployment-configuration/codefresh-publish-template.yaml b/utilities/cloudharness_utilities/deployment-configuration/codefresh-publish-template.yaml new file mode 100644 index 00000000..106e7a5a --- /dev/null +++ b/utilities/cloudharness_utilities/deployment-configuration/codefresh-publish-template.yaml @@ -0,0 +1,7 @@ +stage: 'publish' +type: push +title: REPLACE_ME +candidate: REPLACE_ME +tags: + - ${{DEPLOYMENT_PUBLISH_TAG}} +registry: ${{REGISTRY_PUBLISH_URL}} diff --git a/utilities/cloudharness_utilities/deployment-configuration/codefresh-template.yaml b/utilities/cloudharness_utilities/deployment-configuration/codefresh-template-dev.yaml similarity index 60% rename from utilities/cloudharness_utilities/deployment-configuration/codefresh-template.yaml rename to utilities/cloudharness_utilities/deployment-configuration/codefresh-template-dev.yaml index e0b96c47..4aada583 100644 --- a/utilities/cloudharness_utilities/deployment-configuration/codefresh-template.yaml +++ b/utilities/cloudharness_utilities/deployment-configuration/codefresh-template-dev.yaml @@ -3,6 +3,7 @@ stages: - prepare - build - deploy + - publish steps: main_clone: title: Clone main repository @@ -15,6 +16,14 @@ steps: title: Post main clone type: parallel stage: prepare + steps: + - title: Cloning cloud-harness repository... + type: git-clone + stage: prepare + repo: 'https://github.com/MetaCell/cloud-harness.git' + revision: '${{CLOUDHARNESS_BRANCH}}' + working_directory: . + git: github prepare_deployment: title: "Prepare helm chart" image: python:3.7 @@ -22,14 +31,14 @@ steps: working_directory: . commands: - pip install cloud-harness/utilities - - harness-deployment . cloud-harness -m build -t ${{CF_REVISION}} -d ${{DOMAIN}} -r ${{REGISTRY}} -rs ${{REGISTRY_SECRET}} + - harness-deployment cloud-harness . -m build -t ${{CF_BUILD_ID}} -d ${{DOMAIN}} -r ${{REGISTRY}} -rs ${{REGISTRY_SECRET}} -e dev prepare_deployment_view: commands: - - 'helm template ./deployment/helm --debug -n ${{NAME}}' + - 'helm template ./deployment/helm --debug -n ${{NAMESPACE}}' environment: - ACTION=auth - - KUBE_CONTEXT=${{NAME}} - image: codefresh/cfstep-helm:2.16.1 + - KUBE_CONTEXT=${{NAMESPACE}} + image: codefresh/cfstep-helm:3.4.1 stage: prepare title: 'View helm chart' build_base_images: @@ -51,15 +60,20 @@ steps: REPLACE_ME deployment: stage: deploy - image: codefresh/cfstep-helm:3.0.3 + image: codefresh/cfstep-helm:3.4.1 title: Installing chart environment: - CHART_REF=./deployment/helm - RELEASE_NAME=${{NAMESPACE}} - KUBE_CONTEXT=${{CLUSTER_NAME}} - NAMESPACE=${{NAMESPACE}} - - CHART_VERSION=0.0.1 + - CHART_VERSION=${{DEPLOYMENT_PUBLISH_TAG}} - HELM_REPO_USE_HTTP=false - HELM_REPO_CONTEXT_PATH= - - TIMEOUT=600 - - VALUESFILE_values=./deployment/helm/values.yaml \ No newline at end of file + - TIMEOUT=600s + - VALUESFILE_values=./deployment/helm/values.yaml + publish: + type: parallel + stage: publish + steps: + REPLACE_ME \ No newline at end of file diff --git a/utilities/cloudharness_utilities/deployment-configuration/codefresh-template-prod.yaml b/utilities/cloudharness_utilities/deployment-configuration/codefresh-template-prod.yaml new file mode 100644 index 00000000..175ab6ad --- /dev/null +++ b/utilities/cloudharness_utilities/deployment-configuration/codefresh-template-prod.yaml @@ -0,0 +1,90 @@ +version: '1.0' +stages: + - prepare + - deploy + - publish +steps: + main_clone: + title: Clone main repository + type: git-clone + stage: prepare + repo: '${{CF_REPO_OWNER}}/${{CF_REPO_NAME}}' + revision: '${{CF_BRANCH}}' + git: github + post_main_clone: + title: Post main clone + type: parallel + stage: prepare + steps: + - title: Cloning cloud-harness repository... + type: git-clone + stage: prepare + repo: 'https://github.com/MetaCell/cloud-harness.git' + revision: '${{CLOUDHARNESS_BRANCH}}' + working_directory: . + git: github + prepare_deployment: + title: "Prepare helm chart" + image: python:3.7 + stage: prepare + working_directory: . + commands: + - pip install cloud-harness/utilities + - harness-deployment . cloud-harness -m build -t ${{DEPLOYMENT_TAG}} -d ${{DOMAIN}} -r ${{REGISTRY}} -rs ${{REGISTRY_SECRET}} -e prod + prepare_deployment_view: + commands: + - 'helm template ./deployment/helm --debug -n ${{NAMESPACE}}' + environment: + - ACTION=auth + - KUBE_CONTEXT=${{NAMESPACE}} + image: codefresh/cfstep-helm:3.4.1 + stage: prepare + title: 'View helm chart' + deployment: + stage: deploy + image: codefresh/cfstep-helm:3.4.1 + title: Installing chart + environment: + - CHART_REF=./deployment/helm + - RELEASE_NAME=${{NAMESPACE}} + - KUBE_CONTEXT=${{CLUSTER_NAME}} + - NAMESPACE=${{NAMESPACE}} + - CHART_VERSION=${{DEPLOYMENT_TAG}} + - HELM_REPO_USE_HTTP=false + - HELM_REPO_CONTEXT_PATH= + - TIMEOUT=600s + - VALUESFILE_values=./deployment/helm/values.yaml + approval: + type: pending-approval + stage: publish + title: Approve + description: Approve publication + timeout: + duration: 168 + finalState: approved + publish: + type: parallel + stage: publish + steps: + REPLACE_ME + when: + condition: + all: + whenVarExists: 'includes("${{DEPLOYMENT_PUBLISH_TAG}}", "{{DEPLOYMENT_PUBLISH_TAG}}") == false' + git-tag: + title: Performing git tagging + stage: publish + image: alpine/git:latest + commands: + - git tag ${{DEPLOYMENT_PUBLISH_TAG}} + - ORIGIN=$(git remote get-url origin) + - PROTOCOL=https:// + - REPLACEMENT=${PROTOCOL}${{REPO_TOKEN}}@ + - git remote set-url origin ${ORIGIN/$PROTOCOL/$REPLACEMENT} + - git push origin --tags + when: + condition: + all: + whenVarExists: 'includes("${{DEPLOYMENT_PUBLISH_TAG}}", "{{DEPLOYMENT_PUBLISH_TAG}}") == false' + whenVarExists2: 'includes("${{REPO_TOKEN}}", "{{REPO_TOKEN}}") == false' + diff --git a/utilities/cloudharness_utilities/deployment-configuration/docs.md b/utilities/cloudharness_utilities/deployment-configuration/docs.md new file mode 100644 index 00000000..493f94bc --- /dev/null +++ b/utilities/cloudharness_utilities/deployment-configuration/docs.md @@ -0,0 +1,49 @@ +# cloudharness + +![Version: 0.0.1](https://img.shields.io/badge/Version-0.0.1-informational?style=flat-square) ![AppVersion: 0.0.1](https://img.shields.io/badge/AppVersion-0.0.1-informational?style=flat-square) + +CloudHarness Helm Chart + +## Maintainers + +| Name | Email | Url | +| ---- | ------ | --- | +| Filippo Ledda | filippo@metacell.us | | +| Zoran Sinnema | zoran@metacell.us | | + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| apps | string | Will be filled automatically. | List of applications. | +| backup.active | bool | `true` | Flag to enable/disable backups. | +| backup.dir | string | `"/backups"` | Target directory of backups, the mount point of the persistent volume. | +| backup.keep_days | string | `"7"` | Number of days to keep backups. | +| backup.keep_months | string | `"6"` | Number of months to keep backups. | +| backup.keep_weeks | string | `"4"` | Number of weeks to keep backups. | +| backup.resources.limits.cpu | string | `"50m"` | K8s cpu resource definition. | +| backup.resources.limits.memory | string | `"64Mi"` | K8s memory resource definition. | +| backup.resources.requests.cpu | string | `"25m"` | K8s cpu resource definition. | +| backup.resources.requests.memory | string | `"32Mi"` | K8s memory resource definition. | +| backup.schedule | string | `"@daily"` | Schedule as cronjob expression. | +| backup.suffix | string | `".gz"` | The file suffix added to backup files. | +| domain | string | `"${{DOMAIN}}"` | The root domain. | +| env[0] | object | `{"name":"CH_VERSION","value":"0.0.1"}` | Cloud Harness version | +| env[1] | object | `{"name":"CH_CHART_VERSION","value":"0.0.1"}` | Cloud harness chart version | +| fullnameOverride | string | `""` | ? | +| ingress.enabled | bool | `true` | Flag to enable/disalbe ingress controller. | +| ingress.letsencrypt.email | string | `"filippo@metacell.us"` | Email for letsencrypt. | +| ingress.name | string | `"cloudharness-ingress"` | K8s Name of ingress. | +| ingress.ssl_redirect | bool | `true` | Enables/disables SSL redirect. | +| local | bool | `false` | If set to local, TLS won't be configured. | +| mainapp | string | `"accounts"` | Name of mainapp, routes incoming traffic of root `domaim` to this app. | +| nameOverride | string | `""` | ? | +| namespace | string | `"ch"` | The K8s namespace. | +| privenv[0] | object | `{"name":"CH_SECRET","value":"In God we trust; all others must bring data. ― W. Edwards Deming"}` | Defines a secret as private environment variable that is injected in containers. | +| registry.name | string | `"localhost:5000"` | The docker registry. | +| registry.secret | string | `nil` | Optional secret used for pulling from docker registry. | +| secured_gatekeepers | bool | `true` | Enables/disables Gatekeeper. | +| tag | string | `"latest"` | Docker tag used to pull images. | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.5.0](https://github.com/norwoodj/helm-docs/releases/v1.5.0) diff --git a/utilities/cloudharness_utilities/deployment-configuration/helm/Chart.yaml b/utilities/cloudharness_utilities/deployment-configuration/helm/Chart.yaml index 20d334a2..f294c3e7 100644 --- a/utilities/cloudharness_utilities/deployment-configuration/helm/Chart.yaml +++ b/utilities/cloudharness_utilities/deployment-configuration/helm/Chart.yaml @@ -4,9 +4,7 @@ description: CloudHarness Helm Chart name: cloudharness version: 0.0.1 maintainers: - - name: Facundo Rodriguez - email: facundo@metacell.us - name: Filippo Ledda email: filippo@metacell.us - name: Zoran Sinnema - email: zoran@metacell.us \ No newline at end of file + email: zoran@metacell.us diff --git a/utilities/cloudharness_utilities/deployment-configuration/helm/files/db-mongo-backup.sh b/utilities/cloudharness_utilities/deployment-configuration/helm/files/db-mongo-backup.sh new file mode 100644 index 00000000..30f7067b --- /dev/null +++ b/utilities/cloudharness_utilities/deployment-configuration/helm/files/db-mongo-backup.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +set -e +set -u + +KEEP_DAYS=${BACKUP_KEEP_DAYS} +KEEP_WEEKS=`expr $(((${BACKUP_KEEP_WEEKS} * 7) + 1))` +KEEP_MONTHS=`expr $(((${BACKUP_KEEP_MONTHS} * 31) + 1))` + +mkdir -p "${BACKUP_DIR}/daily/" "${BACKUP_DIR}/weekly/" "${BACKUP_DIR}/monthly/" + +# Clean old files +echo "Cleaning backups older than ${KEEP_DAYS} ..." +find "${BACKUP_DIR}/daily" -maxdepth 1 -mtime +${KEEP_DAYS} -name "*${BACKUP_SUFFIX}" -print -delete +find "${BACKUP_DIR}/weekly" -maxdepth 1 -mtime +${KEEP_WEEKS} -name "*${BACKUP_SUFFIX}" -print -delete +find "${BACKUP_DIR}/monthly" -maxdepth 1 -mtime +${KEEP_MONTHS} -name "*${BACKUP_SUFFIX}" -print -delete + +DFILE="${BACKUP_DIR}/daily/`date +%Y-%m-%d-%H%M%S`${BACKUP_SUFFIX}" +WFILE="${BACKUP_DIR}/weekly/`date +%G-%V`${BACKUP_SUFFIX}" +MFILE="${BACKUP_DIR}/monthly/`date +%Y-%m`${BACKUP_SUFFIX}" + +# Dump mongo database +/usr/bin/mongodump -h $DB_HOST -u $DB_USER -p $DB_PASS --archive=$DFILE --gzip + +# Use hardlink instead of copy to save space +if [ -d "${DFILE}" ]; then + WFILENEW="${WFILE}-new" + MFILENEW="${MFILE}-new" + rm -rf "${WFILENEW}" "${MFILENEW}" + mkdir "${WFILENEW}" "${MFILENEW}" + ln -f "${DFILE}/"* "${WFILENEW}/" + ln -f "${DFILE}/"* "${MFILENEW}/" + rm -rf "${WFILE}" "${MFILE}" + mv -v "${WFILENEW}" "${WFILE}" + mv -v "${MFILENEW}" "${MFILE}" +else + ln -vf "${DFILE}" "${WFILE}" + ln -vf "${DFILE}" "${MFILE}" +fi \ No newline at end of file diff --git a/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-database-mongo-backup.yaml b/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-database-mongo-backup.yaml new file mode 100644 index 00000000..e357c7a8 --- /dev/null +++ b/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-database-mongo-backup.yaml @@ -0,0 +1,64 @@ +{{ define "deploy_utils.database.mongo.backup"}} +apiVersion: batch/v1beta1 +kind: CronJob +metadata: + name: "{{ .app.harness.database.name }}-backup" +spec: + schedule: {{ .root.Values.backup.schedule | quote }} + jobTemplate: + spec: + template: + spec: + affinity: + podAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: service + operator: In + values: + - db + topologyKey: kubernetes.io/hostname + containers: + - name: "{{ .app.harness.database.name }}-backup" + image: {{ .app.harness.database.mongo.image }} + imagePullPolicy: IfNotPresent + command: ["/bin/bash"] + args: + - -c + - | {{ range .root.Files.Lines "files/db-mongo-backup.sh" }} + {{ . }} + {{ end }} + env: + - name: DB_USER + value: {{ .app.harness.database.user }} + - name: DB_PASS + value: {{ .app.harness.database.pass }} + - name: DB_HOST + value: {{ .app.harness.database.name }} + - name: BACKUP_KEEP_DAYS + value: {{ .root.Values.backup.keep_days | quote }} + - name: BACKUP_KEEP_WEEKS + value: {{ .root.Values.backup.keep_weeks | quote }} + - name: BACKUP_KEEP_MONTHS + value: {{ .root.Values.backup.keep_months | quote }} + - name: BACKUP_SUFFIX + value: {{ .root.Values.backup.suffix | quote }} + - name: BACKUP_DIR + value: {{ (printf "%s/mongo/%s" .root.Values.backup.dir .app.harness.database.name ) | quote }} + volumeMounts: + - name: "db-backup" + mountPath: /backups + resources: + requests: + memory: {{ .root.Values.backup.resources.requests.memory | default "32Mi" }} + cpu: {{ .root.Values.backup.resources.requests.cpu | default "25Mi" }} + limits: + memory: {{ .root.Values.backup.resources.limits.memory | default "64Mi" }} + cpu: {{ .root.Values.backup.resources.limits.cpu | default "50mi" }} + restartPolicy: OnFailure + volumes: + - name: "db-backup" + persistentVolumeClaim: + claimName: "db-backup" +{{ end }} \ No newline at end of file diff --git a/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-database-mongo.yaml b/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-database-mongo.yaml new file mode 100644 index 00000000..e27856c4 --- /dev/null +++ b/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-database-mongo.yaml @@ -0,0 +1,26 @@ +{{- define "deploy_utils.database.mongo" }} + image: {{ .app.harness.database.mongo.image }} + env: + - name: MONGO_INITDB_ROOT_USERNAME + value: {{ .app.harness.database.user | quote }} + - name: MONGO_INITDB_ROOT_PASSWORD + value: {{ .app.harness.database.pass | quote }} + livenessProbe: + exec: + command: + - mongo + - --eval + - "db.adminCommand('ping')" + initialDelaySeconds: 30 + timeoutSeconds: 5 + failureThreshold: 6 + readinessProbe: + exec: + command: + - mongo + - --eval + - "db.adminCommand('ping')" + initialDelaySeconds: 5 + timeoutSeconds: 5 + failureThreshold: 6 +{{- end }} \ No newline at end of file diff --git a/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-database-neo4j-backup.yaml b/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-database-neo4j-backup.yaml new file mode 100644 index 00000000..f84626ac --- /dev/null +++ b/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-database-neo4j-backup.yaml @@ -0,0 +1,2 @@ +{{- define "deploy_utils.database.neo4j.backup" }} +{{- end }} \ No newline at end of file diff --git a/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-database-neo4j.yaml b/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-database-neo4j.yaml new file mode 100644 index 00000000..1116bbb1 --- /dev/null +++ b/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-database-neo4j.yaml @@ -0,0 +1,20 @@ +{{- define "deploy_utils.database.neo4j" }} + image: {{ .app.harness.database.neo4j.image }} + env: + - name: NEO4J_dbms_directories_data + value: /data/db/data + - name: NEO4J_dbms_directories_logs + value: /data/db/logs + - name: NEO4J_dbms_directories_metrics + value: /data/db/metrics + - name: NEO4J_dbms_memory_size + value: {{ .app.harness.database.neo4j.memory.size }} + - name: NEO4J_dbms_memory_pagecache_size + value: {{ .app.harness.database.neo4j.memory.pagecache.size }} + - name: NEO4J_dbms_memory_heap_initial__size + value: {{ .app.harness.database.neo4j.memory.heap.initial }} + - name: NEO4J_dbms_memory_heap_max__size + value: {{ .app.harness.database.neo4j.memory.heap.max }} + - name: NEO4J_dbms_security_auth__enabled + value: {{ .app.harness.database.neo4j.dbms_security_auth_enabled | quote }} +{{- end }} \ No newline at end of file diff --git a/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-database-postgres-backup.yaml b/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-database-postgres-backup.yaml new file mode 100644 index 00000000..12cc3816 --- /dev/null +++ b/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-database-postgres-backup.yaml @@ -0,0 +1,58 @@ +{{ define "deploy_utils.database.postgres.backup"}} +apiVersion: batch/v1beta1 +kind: CronJob +metadata: + name: "{{ .app.harness.database.name }}-backup" +spec: + schedule: {{ .root.Values.backup.schedule | quote }} + jobTemplate: + spec: + template: + spec: + securityContext: + runAsUser: 999 + runAsGroup: 999 + containers: + - name: "{{ .app.harness.database.name }}-backup" + imagePullPolicy: IfNotPresent + image: prodrigestivill/postgres-backup-local + command: ["/bin/bash"] + args: ["-c" , "./backup.sh"] + env: + - name: POSTGRES_HOST + value: {{ .app.harness.database.name | quote }} + - name: POSTGRES_DB + value: {{ (index .app.harness.database .app.harness.database.type).initialdb | quote }} + - name: POSTGRES_USER + value: {{ .app.harness.database.user | quote }} + - name: POSTGRES_PASSWORD + value: {{ .app.harness.database.pass | quote }} + - name: SCHEDULE + value: {{ .root.Values.backup.schedule | quote }} + - name: BACKUP_KEEP_DAYS + value: {{ .root.Values.backup.keep_days | quote }} + - name: BACKUP_KEEP_WEEKS + value: {{ .root.Values.backup.keep_weeks |quote }} + - name: BACKUP_KEEP_MONTHS + value: {{ .root.Values.backup.keep_months | quote }} + - name: BACKUP_SUFFIX + value: {{ .root.Values.backup.suffix | quote }} + - name: BACKUP_DIR + value: {{ (printf "%s/postgres/%s" .root.Values.backup.dir .app.harness.database.name) | quote }} + volumeMounts: + - name: "db-backup" + mountPath: /backups + resources: + requests: + memory: {{ .root.Values.backup.resources.requests.memory | default "32Mi" }} + cpu: {{ .root.Values.backup.resources.requests.cpu | default "25Mi" }} + limits: + memory: {{ .root.Values.backup.resources.limits.memory | default "64Mi" }} + cpu: {{ .root.Values.backup.resources.limits.cpu | default "50mi" }} + restartPolicy: OnFailure + volumes: + - name: "db-backup" + persistentVolumeClaim: + claimName: "db-backup" + +{{ end }} \ No newline at end of file diff --git a/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-database-postgres.yaml b/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-database-postgres.yaml new file mode 100644 index 00000000..1c272997 --- /dev/null +++ b/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-database-postgres.yaml @@ -0,0 +1,12 @@ +{{- define "deploy_utils.database.postgres" }} + image: {{ .app.harness.database.postgres.image }} + env: + - name: POSTGRES_DB + value: {{ .app.harness.database.postgres.initialdb | quote }} + - name: POSTGRES_USER + value: {{ .app.harness.database.user | quote }} + - name: POSTGRES_PASSWORD + value: {{ .app.harness.database.pass | quote }} + - name: PGDATA + value: /data/db/pgdata +{{- end }} \ No newline at end of file diff --git a/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-database.yaml b/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-database.yaml new file mode 100644 index 00000000..3d52f836 --- /dev/null +++ b/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-database.yaml @@ -0,0 +1,124 @@ +{{- if .Values.backup.active }} +--- +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: "db-backup" + namespace: {{ .Values.namespace }} +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .Values.backup.volumesize }} +--- +{{- end }} +{{- define "deploy_utils.database" }} +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: {{ .app.harness.database.name | quote }} + namespace: {{ .root.Values.namespace }} +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .app.harness.database.size }} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .app.harness.database.name | quote }} + namespace: {{ .root.Values.namespace }} +spec: + replicas: 1 + selector: + matchLabels: + app: {{ .app.harness.database.name | quote }} + template: + metadata: + labels: + app: {{ .app.harness.database.name | quote }} + service: db + spec: + affinity: + podAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: service + operator: In + values: + - db + topologyKey: kubernetes.io/hostname + containers: + - name: {{ .app.harness.database.name | quote }} + imagePullPolicy: IfNotPresent + {{ include (print "deploy_utils.database." .app.harness.database.type) (dict "root" .root "app" .app) }} + ports: + {{- range $port := (index .app.harness.database .app.harness.database.type).ports }} + - name: {{ $port.name }} + containerPort: {{ $port.port }} + {{- end }} + resources: + requests: + memory: {{ .app.harness.database.resources.requests.memory | default "32Mi" }} + cpu: {{ .app.harness.database.resources.requests.cpu | default "25m" }} + limits: + memory: {{ .app.harness.database.resources.limits.memory | default "64Mi" }} + cpu: {{ .app.harness.database.resources.limits.cpu | default "50m" }} + volumeMounts: + - name: {{ .app.harness.database.name | quote }} + mountPath: /data/db + {{- if .root.Values.backup.active }} + - name: "db-backup" + mountPath: /backup + {{- end }} + volumes: + - name: {{ .app.harness.database.name | quote }} + persistentVolumeClaim: + claimName: {{ .app.harness.database.name | quote }} + {{- if .root.Values.backup.active }} + - name: "db-backup" + persistentVolumeClaim: + claimName: "db-backup" + {{- end }} +--- +{{- if .root.Values.backup.active }} +{{- include (print "deploy_utils.database." .app.harness.database.type ".backup") . }} +{{- end }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ .app.harness.database.name | quote }} + namespace: {{ .root.Values.namespace }} + labels: + app: {{ .app.harness.deployment.name | quote }} +{{ include "deploy_utils.labels" .root | indent 4 }} +spec: + type: ClusterIP + selector: + app: {{ .app.harness.database.name | quote }} + ports: + {{- range $port := (index .app.harness.database .app.harness.database.type).ports }} + - name: {{ $port.name }} + port: {{ $port.port }} + {{- end }} +--- +{{ end }} +{{- range $app := .Values.apps }} + {{- if $app.harness.database.auto }} + {{ include "deploy_utils.database" (dict "root" $ "app" $app) }} + {{- end }} + {{- range $subapp := $app }} + {{- if contains "map" (typeOf $subapp) }} + {{- if hasKey $subapp "harness"}} + {{- if and (hasKey $subapp.harness "database") $subapp.harness.database.auto }} + {{ include "deploy_utils.database" (dict "root" $ "app" $subapp) }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} diff --git a/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-deployments.yaml b/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-deployments.yaml index d264f78f..abd47a99 100644 --- a/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-deployments.yaml +++ b/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-deployments.yaml @@ -32,9 +32,18 @@ spec: - name: {{ .app.harness.deployment.name| default "cloudharness-docs" | quote }} image: {{ .app.harness.deployment.image }} imagePullPolicy: {{ include "deploy_utils.pullpolicy" .root }} + {{- if .app.harness.deployment.command }} + command: {{ .app.harness.deployment.command }} + {{- end }} + {{- if .app.harness.deployment.args }} + args: {{ .app.harness.deployment.args }} + {{- end }} env: {{- include "deploy_utils.env" .root | nindent 8 }} {{- include "deploy_utils.privenv" .root | nindent 8 }} + {{- if .app.harness.env }} + {{- .app.harness.env | toYaml | nindent 8 }} + {{- end }} {{- if .app.harness.secrets }} {{- range $secret := .app.harness.secrets }} - name: {{ print $secret.name "-" $secret.key }} @@ -44,6 +53,22 @@ spec: key: {{ print $secret.key }} {{- end }} {{- end }} +{{ if .app.harness.livenessProbe }} + livenessProbe: + httpGet: + path: {{ .app.harness.livenessProbe.path }} + port: {{ .app.harness.deployment.port | default 8080 }} + periodSeconds: {{ .app.harness.livenessProbe.periodSeconds | default 10 }} + initialDelaySeconds: {{ .app.harness.livenessProbe.initialDelaySeconds | default 0 }} +{{ end }} +{{ if .app.harness.readinessProbe }} + readinessProbe: + httpGet: + path: {{ .app.harness.readinessProbe.path }} + port: {{ .app.harness.deployment.port | default 8080 }} + periodSeconds: {{ .app.harness.readinessProbe.periodSeconds | default 10 }} + initialDelaySeconds: {{ .app.harness.readinessProbe.initialDelaySeconds | default 0 }} +{{ end }} ports: - containerPort: {{ .app.harness.deployment.port | default 8080 }} resources: @@ -61,6 +86,13 @@ spec: - name: {{ .app.harness.deployment.volume.name }} mountPath: {{ .app.harness.deployment.volume.mountpath }} {{- end }} + {{- $app := .app}} + {{- range $resource := .app.harness.resources }} + - name: "{{ $app.harness.deployment.name }}-{{ $resource.name }}" + mountPath: {{ $resource.dst }} + subPath: {{ base $resource.dst }} + readOnly: true + {{- end}} volumes: - name: cloudharness-allvalues configMap: @@ -70,14 +102,36 @@ spec: persistentVolumeClaim: claimName: {{ .app.harness.deployment.volume.name }} {{- end }} - + {{ $app := .app }} + {{- range $resource := .app.harness.resources }} + - name: "{{ $app.harness.deployment.name }}-{{ $resource.name }}" + configMap: + name: "{{ $app.harness.deployment.name }}-{{ $resource.name }}" + {{- end }} --- {{- end }} + +{{- define "deploy_utils.resource"}} +kind: ConfigMap +apiVersion: v1 +metadata: + name: "{{ .app.harness.deployment.name }}-{{ .resource.name }}" + labels: + app: {{ .app.harness.deployment.name | quote }} + {{ include "deploy_utils.labels" .root | indent 4 }} +data: + {{ base .resource.dst }}: {{ tpl (.root.Files.Get (print "resources/" .app.harness.deployment.name "/" .resource.src)) .root | quote }} +--- +{{- end}} + {{- range $app := .Values.apps }} {{- if and (hasKey $app "port") $app.harness.deployment.auto | default false }} --- {{- include "deploy_utils.deployment" (dict "root" $ "app" $app) }} + {{- range $resource := $app.harness.resources }} + {{- include "deploy_utils.resource" (dict "app" $app "resource" $resource "root" $) }} {{- end }} + {{- end }} {{- range $subapp := $app }} {{- if contains "map" (typeOf $subapp) }} {{- if hasKey $subapp "harness" }} diff --git a/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-gatekeepers.yaml b/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-gatekeepers.yaml index 3c4ab65e..c57898b3 100644 --- a/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-gatekeepers.yaml +++ b/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-gatekeepers.yaml @@ -1,5 +1,4 @@ {{/* Secured Services/Deployments */}} - {{- define "deploy_utils.securedservice" }} {{- $tls := not (not .root.Values.tls) }} apiVersion: v1 @@ -11,7 +10,7 @@ metadata: data: proxy.yml: |- verbose: true - discovery-url: {{ ternary "https" "http" $tls}}://{{ .root.Values.apps.accounts.subdomain }}.{{ .root.Values.domain }}/auth/realms/{{ .root.Values.namespace }} + discovery-url: {{ ternary "https" "http" $tls}}://{{ .root.Values.apps.accounts.harness.subdomain }}.{{ .root.Values.domain }}/auth/realms/{{ .root.Values.namespace }} client-id: {{ .root.Values.apps.accounts.webclient.id | quote }} client-secret: {{ .root.Values.apps.accounts.webclient.secret }} secure-cookie: {{ $tls }} @@ -22,8 +21,6 @@ data: redirection-url: {{ ternary "https" "http" $tls }}://{{ .app.harness.subdomain }}.{{ .root.Values.domain }} encryption-key: AgXa7xRcoClDEU0ZDSH4X0XhL5Qy2Z2j upstream-url: http://{{ .app.harness.service.name }}.{{ .app.namespace | default .root.Release.Namespace }}:{{ .app.harness.service.port | default 80}} - scopes: - - vpn-user {{ if .app.harness.secured }} {{ with .app.harness.uri_role_mapping }} resources: @@ -68,7 +65,7 @@ spec: {{ include "deploy_utils.etcHosts" .root | indent 6 }} containers: - name: {{ .app.harness.service.name | quote }} - image: "quay.io/louketo/louketo-proxy:1.0.0" + image: "gcr.io/metacellllc/louketo-proxy:1.0.0" imagePullPolicy: IfNotPresent {{ if .root.Values.local }} securityContext: diff --git a/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-services.yaml b/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-services.yaml index 1385bfed..4c58a815 100644 --- a/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-services.yaml +++ b/utilities/cloudharness_utilities/deployment-configuration/helm/templates/auto-services.yaml @@ -13,6 +13,7 @@ spec: app: {{ .app.harness.deployment.name| quote }} ports: - port: {{ .app.harness.service.port }} + targetPort: {{ .app.harness.deployment.port }} name: http --- {{- end }} diff --git a/utilities/cloudharness_utilities/deployment-configuration/helm/templates/certs/letsencrypt.yaml b/utilities/cloudharness_utilities/deployment-configuration/helm/templates/certs/letsencrypt.yaml index 9d00da02..67765b99 100644 --- a/utilities/cloudharness_utilities/deployment-configuration/helm/templates/certs/letsencrypt.yaml +++ b/utilities/cloudharness_utilities/deployment-configuration/helm/templates/certs/letsencrypt.yaml @@ -1,4 +1,4 @@ -{{ if not .Values.local }} +{{- if and (not .Values.local) (not (not .Values.tls)) }} apiVersion: cert-manager.io/v1alpha2 kind: ClusterIssuer metadata: @@ -8,7 +8,7 @@ spec: server: https://acme-v02.api.letsencrypt.org/directory email: {{ .Values.ingress.letsencrypt.email }} privateKeySecretRef: - name: {{ .Values.tls }} + name: tls-secret solvers: - http01: ingress: diff --git a/utilities/cloudharness_utilities/deployment-configuration/helm/templates/ingress.yaml b/utilities/cloudharness_utilities/deployment-configuration/helm/templates/ingress.yaml index e5e3e243..1beff6d8 100644 --- a/utilities/cloudharness_utilities/deployment-configuration/helm/templates/ingress.yaml +++ b/utilities/cloudharness_utilities/deployment-configuration/helm/templates/ingress.yaml @@ -1,49 +1,62 @@ +{{- define "deploy_utils.ingress.http" }} + {{ $domain := .root.Values.domain }} + {{ $secured_gatekeepers := and .root.Values.secured_gatekeepers }} + http: + paths: + - path: /(.*) + backend: + serviceName: {{ .app.harness.service.name }}{{- if (and .app.harness.secured $secured_gatekeepers) }}-gk{{- end }} + servicePort: {{- if (and .app.harness.secured $secured_gatekeepers) }} 8080 {{- else }} {{ .app.harness.service.port | default 80 }}{{- end }} +{{- end }} +{{- define "deploy_utils.ingress.service" }} + {{ $domain := .root.Values.domain }} + {{ $secured_gatekeepers := and .root.Values.secured_gatekeepers }} + {{ $app := get .root.Values.apps (print .service_name | snakecase) }} + - path: /proxy/{{ $app.harness.service.name }}/(.*) + backend: + serviceName: {{ $app.harness.service.name }}{{- if (and $app.harness.secured $secured_gatekeepers) }}-gk{{- end }} + servicePort: {{- if (and $app.harness.secured $secured_gatekeepers) }} 8080 {{- else }} {{ $app.harness.service.port | default 80 }}{{- end }} +{{- end }} {{- if .Values.ingress.enabled }} {{ $domain := .Values.domain }} {{ $tls := not (not .Values.tls) }} - {{ $secured_gatekeepers := and .Values.secured_gatekeepers }} +{{ $mainapp := .Values.mainapp }} apiVersion: extensions/v1beta1 kind: Ingress metadata: name: {{ .Values.ingress.name | quote }} annotations: - {{- if not .Values.local }} - kubernetes.io/tls-acme: 'true' kubernetes.io/ingress.class: nginx + {{- if and (not .Values.local) $tls }} + kubernetes.io/tls-acme: 'true' cert-manager.io/cluster-issuer: {{ printf "%s-%s" "letsencrypt" .Values.namespace }} {{- end }} nginx.ingress.kubernetes.io/ssl-redirect: {{ (and $tls .Values.ingress.ssl_redirect) | quote }} nginx.ingress.kubernetes.io/proxy-body-size: '10m' nginx.ingress.kubernetes.io/from-to-www-redirect: 'true' + nginx.ingress.kubernetes.io/rewrite-target: /$1 spec: rules: {{- range $app := .Values.apps }} - {{- if $app.harness.domain }} + {{- if (eq $app.harness.name $mainapp) }} - host: {{ $domain | quote }} - http: - paths: - - path: / - backend: - serviceName: {{- if (and $app.harness.secured $secured_gatekeepers) }} "{{ $app.harness.service.name }}-gk" {{- else }} {{ $app.harness.service.name | quote }}{{- end }} - servicePort: {{- if (and $app.harness.secured $secured_gatekeepers) }} 8080 {{- else }} {{ $app.harness.service.port | default 80 }}{{- end }} - {{- else if $app.harness.subdomain }} + {{ include "deploy_utils.ingress.http" (dict "root" $ "app" $app) }} + {{- end }} + {{- if $app.harness.domain }} + - host: {{ $app.harness.domain | quote }} + {{ include "deploy_utils.ingress.http" (dict "root" $ "app" $app) }} + {{- end }} + {{- if $app.harness.subdomain }} - host: {{ printf "%s.%s" $app.harness.subdomain $domain | quote }} - http: - paths: - - path: / - backend: - serviceName: {{- if (and $app.harness.secured $secured_gatekeepers) }} "{{ $app.harness.service.name }}-gk" {{- else }} {{ $app.harness.service.name | quote }}{{- end }} - servicePort: {{- if (and $app.harness.secured $secured_gatekeepers) }} 8080 {{- else }} {{ $app.harness.service.port | default 80 }}{{- end }} + {{ include "deploy_utils.ingress.http" (dict "root" $ "app" $app) }} + {{- range $service := $app.harness.use_services }} + {{ include "deploy_utils.ingress.service" (dict "root" $ "service_name" $service.name) }} + {{- end }} {{- range $subapp := $app }} - {{- if contains "map" (typeOf $subapp) }} - {{- if and $subapp (hasKey $subapp "harness.subdomain") }} + {{- if contains "map" (typeOf $subapp) }} + {{- if and $subapp (hasKey $subapp "harness.subdomain") }} - host: {{ printf "%s.%s.%s" $subapp.harness.subdomain $app.harness.subdomain $domain | quote }} - http: - paths: - - path: / - backend: - serviceName: {{- if (and $app.harness.secured $secured_gatekeepers) }} "{{ $subapp.harness.service.name }}-gk" {{- else }} {{ $subapp.harness.service.name | quote }}{{- end }} - servicePort: {{- if (and $app.harness.secured $secured_gatekeepers) }} 8080 {{- else }} {{ $subapp.harness.service.port | default 80 }}{{- end }} + {{ include "deploy_utils.ingress.http" (dict "root" $ "app" $subapp) }} {{- end }} {{- end }} {{- end }} @@ -55,10 +68,16 @@ spec: {{- range $app := .Values.apps }} {{- if $app.harness.subdomain }} - {{ printf "%s.%s" $app.harness.subdomain $domain | quote }} - {{- else if $app.domain }} - - {{ $domain | quote }} {{- end }} + {{- if $app.harness.domain }} + {{- if ne $app.harness.domain $domain }} + - {{ $app.harness.domain | quote }} + {{- end }} + {{- end }} + {{- end }} + {{- if $mainapp }} + - {{ $domain | quote }} {{- end }} - secretName: {{ $tls | quote }} + secretName: tls-secret {{- end }} {{- end }} \ No newline at end of file diff --git a/utilities/cloudharness_utilities/deployment-configuration/helm/templates/tls-secret.yaml b/utilities/cloudharness_utilities/deployment-configuration/helm/templates/tls-secret.yaml index 9c08fb4b..ac871d2f 100644 --- a/utilities/cloudharness_utilities/deployment-configuration/helm/templates/tls-secret.yaml +++ b/utilities/cloudharness_utilities/deployment-configuration/helm/templates/tls-secret.yaml @@ -2,7 +2,7 @@ apiVersion: v1 kind: Secret metadata: - name: {{ .Values.tls | quote }} + name: tls-secret type: kubernetes.io/tls data: tls.crt: {{ .Files.Get "resources/certs/tls.crt" | b64enc | quote }} diff --git a/utilities/cloudharness_utilities/deployment-configuration/helm/values.yaml b/utilities/cloudharness_utilities/deployment-configuration/helm/values.yaml index e69de29b..11646d46 100644 --- a/utilities/cloudharness_utilities/deployment-configuration/helm/values.yaml +++ b/utilities/cloudharness_utilities/deployment-configuration/helm/values.yaml @@ -0,0 +1,73 @@ +# -- If set to local, TLS won't be configured. +local: false +# -- Enables/disables Gatekeeper. +secured_gatekeepers: true +# -- ? +nameOverride: "" +# -- ? +fullnameOverride: "" +# -- The root domain. +domain: ${{DOMAIN}} +# -- The K8s namespace. +namespace: ch +# -- Name of mainapp, routes incoming traffic of root `domaim` to this app. +mainapp: accounts +registry: + # -- The docker registry. + name: "localhost:5000" + # -- Optional secret used for pulling from docker registry. + secret: +# -- Docker tag used to pull images. +tag: latest +# -- List of applications. +# @default -- Will be filled automatically. +apps: {} +env: + # -- Cloud Harness version + - name: CH_VERSION + value: 0.0.1 + # -- Cloud harness chart version + - name: CH_CHART_VERSION + value: 0.0.1 +privenv: + # -- Defines a secret as private environment variable that is injected in containers. + - name: CH_SECRET + value: In God we trust; all others must bring data. ― W. Edwards Deming +ingress: + # -- Flag to enable/disalbe ingress controller. + enabled: true + # -- K8s Name of ingress. + name: cloudharness-ingress + # -- Enables/disables SSL redirect. + ssl_redirect: true + letsencrypt: + # -- Email for letsencrypt. + email: filippo@metacell.us +backup: + # -- Flag to enable/disable backups. + active: true + # -- Number of days to keep backups. + keep_days: "7" + # -- Number of weeks to keep backups. + keep_weeks: "4" + # -- Number of months to keep backups. + keep_months: "6" + # -- Schedule as cronjob expression. + schedule: "*/5 * * * *" + # -- The file suffix added to backup files. + suffix: ".gz" + # -- The volume size for backups (all backups share the same volume) + volumesize: "2Gi" + # -- Target directory of backups, the mount point of the persistent volume. + dir: "/backups" + resources: + requests: + # -- K8s memory resource definition. + memory: "32Mi" + # -- K8s cpu resource definition. + cpu: "25m" + limits: + # -- K8s memory resource definition. + memory: "64Mi" + # -- K8s cpu resource definition. + cpu: "50m" diff --git a/utilities/cloudharness_utilities/deployment-configuration/launch.json b/utilities/cloudharness_utilities/deployment-configuration/launch.json new file mode 100644 index 00000000..b3e96bec --- /dev/null +++ b/utilities/cloudharness_utilities/deployment-configuration/launch.json @@ -0,0 +1,4 @@ +{ + "version": "0.2.0", + "configurations": [] +} \ No newline at end of file diff --git a/utilities/cloudharness_utilities/deployment-configuration/skaffold-template.yaml b/utilities/cloudharness_utilities/deployment-configuration/skaffold-template.yaml new file mode 100644 index 00000000..91c45143 --- /dev/null +++ b/utilities/cloudharness_utilities/deployment-configuration/skaffold-template.yaml @@ -0,0 +1,23 @@ +apiVersion: skaffold/v2beta11 +kind: Config +build: + tagPolicy: + sha256: {} + artifacts: [] +deploy: + + helm: + flags: + upgrade: + - --install + releases: + - name: + chartPath: deployment/helm + #wait: true + #valuesFiles: + #- helm-skaffold-values.yaml + skipBuildDependencies: true # Skip helm dep build + artifactOverrides: + apps: + overrides: + apps: {} \ No newline at end of file diff --git a/utilities/cloudharness_utilities/deployment-configuration/value-template.yaml b/utilities/cloudharness_utilities/deployment-configuration/value-template.yaml index 0b2934a4..fed799a7 100644 --- a/utilities/cloudharness_utilities/deployment-configuration/value-template.yaml +++ b/utilities/cloudharness_utilities/deployment-configuration/value-template.yaml @@ -1,26 +1,100 @@ harness: - name: + # -- If specified, an ingress will be created at [subdomain].[.Values.domain] subdomain: + # -- If specified, an ingress will be created at [domain] domain: + # -- Application dependencies are used to define what is required in the deployment when --include (-i) is used. Specify application names in the list. + dependencies: + # -- Hard dependencies indicate that the application may not start without these other applications. + hard: [] + # -- Hard dependencies indicate that the application will work partially without these other applications. + soft: [] + # -- Hard dependencies indicate that the application Docker image build requires these base/common images + build: [] + # -- When true, the application is shielded with a getekeeper secured: false + # -- Uri/Role mapping for the gatekeeper uri_role_mapping: - uri: /* roles: - administrator + # -- Defines reference deployment parameters. Values maps to k8s spec deployment: + # -- When true, enables automatic deployment auto: false + # -- Number of pod replicas for the deployment. replicas: 1 + # -- Docker image url. Leave blank to leave Cloudharness automatic image name assignment. image: + # -- Deployment name. Leave blank to leave Cloudharness automatic image name assignment. name: - port: 8081 + # -- Deployment port. + port: 8080 + # -- Deployment resources. resources: requests: memory: "32Mi" - cpu: "25m" + cpu: "10m" limits: memory: "500Mi" cpu: "500m" + # -- Defines automatic service parameters. service: + # -- When true, enables automatic service auto: true + # -- Service name. Leave blank to leave Cloudharness automatic image name assignment. name: - port: 80 \ No newline at end of file + # -- Service port. + port: 80 + # -- Specify which services this application uses in the frontend to create proxy ingresses. e.g. - name: mnp-checkout + use_services: [] + # -- Reference database specs + database: + # -- When true, enables automatic database deployment + auto: false + # -- Database deployment name. Leave blank to leave Cloudharness automatic image name assignment. + name: + # -- supported db types: mongo, postgres, neo4j + type: + size: 1Gi + # -- database username + user: mnp + # -- database password + pass: metacell + # -- settings for mongo database (for type==mongo) + mongo: + image: mongo:latest + ports: + - name: http + port: 27017 + # -- settings for postgers database (for type==postgres) + postgres: + image: postgres:latest + initialdb: cloudharness + ports: + - name: http + port: 5432 + # -- settings for neo4j database (for type==neo4j) + neo4j: + image: neo4j:latest + memory: + size: 256M + pagecache: + size: 64M + heap: + initial: 64M + max: 128M + dbms_security_auth_enabled: "false" + ports: + - name: http + port: 7474 + - name: bolt + port: 7687 + # -- database deployment resources + resources: + requests: + memory: "512Mi" + cpu: "100m" + limits: + memory: "2Gi" + cpu: "1000m" \ No newline at end of file diff --git a/utilities/cloudharness_utilities/deployment-configuration/values-template.yaml b/utilities/cloudharness_utilities/deployment-configuration/values-template.yaml index 913c9221..e69de29b 100644 --- a/utilities/cloudharness_utilities/deployment-configuration/values-template.yaml +++ b/utilities/cloudharness_utilities/deployment-configuration/values-template.yaml @@ -1,27 +0,0 @@ -local: false -secured_gatekeepers: true -nameOverride: "" -fullnameOverride: "" -domain: ${{DOMAIN}} -namespace: ch -registry: - name: "localhost:5000" - secret: -tag: latest -serviceaccount: argo-workflows -apps: - FILL_ME -env: - - name: CH_VERSION - value: 0.0.1 - - name: CH_CHART_VERSION - value: 0.0.1 -privenv: - - name: CH_SECRET - value: In God we trust; all others must bring data. ― W. Edwards Deming -ingress: - enabled: true - name: cloudharness-ingress - ssl_redirect: true - letsencrypt: - email: facundo@metacell.us \ No newline at end of file diff --git a/utilities/cloudharness_utilities/deployment-configuration/vscode-debug-template.json b/utilities/cloudharness_utilities/deployment-configuration/vscode-debug-template.json new file mode 100644 index 00000000..8eabd715 --- /dev/null +++ b/utilities/cloudharness_utilities/deployment-configuration/vscode-debug-template.json @@ -0,0 +1,13 @@ +{ + "name": "CloudHarness: Run/Debug", + "type": "cloudcode.kubernetes", + "request": "launch", + "skaffoldConfig": "${workspaceFolder}/skaffold.yaml", + "watch": true, + "cleanUp": false, + "portForward": true, + "imageRegistry": "localhost:5000", + "debug": [ + + ] +} \ No newline at end of file diff --git a/utilities/cloudharness_utilities/dev_utils.py b/utilities/cloudharness_utilities/dev_utils.py new file mode 100644 index 00000000..461b95d8 --- /dev/null +++ b/utilities/cloudharness_utilities/dev_utils.py @@ -0,0 +1,159 @@ +import os +import logging +import json + +from cloudharness_utilities.constants import HELM_CHART_PATH, DEPLOYMENT_CONFIGURATION_PATH, DEPLOYMENT_PATH, \ + BASE_IMAGES_PATH, STATIC_IMAGES_PATH +from cloudharness_utilities.helm import KEY_APPS, KEY_HARNESS, KEY_DEPLOYMENT +from cloudharness_utilities.utils import get_template, dict_merge, find_dockerfiles_paths, app_name_from_path, \ + find_file_paths, merge_to_yaml_file, get_json_template + + +def create_skaffold_configuration(root_paths, helm_values, output_path='.', manage_task_images=True): + skaffold_conf = get_template('skaffold-template.yaml', True) + apps = helm_values[KEY_APPS] + artifacts = {} + overrides = {} + release_config = skaffold_conf['deploy']['helm']['releases'][0] + release_config['name'] = helm_values['namespace'] + release_config['namespace'] = helm_values['namespace'] + + def build_artifact(app_name, root_path, requirements=None, dockerfile_path=''): + artifact_spec = { + 'image': app_name, + 'context': root_path, + 'docker': { + 'dockerfile': os.path.join(dockerfile_path, 'Dockerfile'), + 'buildArgs': { + 'REGISTRY': helm_values["registry"]["name"], + 'TAG': helm_values["tag"] + } + } + } + if requirements: + artifact_spec['requires'] = [{'image': req, 'alias': req.replace('-', '_').upper()} for req in requirements] + return artifact_spec + + release_config['artifactOverrides'][KEY_APPS] = {} + for root_path in root_paths: + skaffold_conf = dict_merge(skaffold_conf, get_template( + os.path.join(root_path, DEPLOYMENT_CONFIGURATION_PATH, 'skaffold-template.yaml'))) + apps_path = os.path.join(root_path, 'applications') + + base_dockerfiles = find_dockerfiles_paths(os.path.join(root_path, BASE_IMAGES_PATH)) + + base_images = [] + for dockerfile_path in base_dockerfiles: + context_path = os.path.relpath(root_path, output_path) + app_name = app_name_from_path(os.path.basename(dockerfile_path)) + base_images.append(app_name) + artifacts[app_name] = build_artifact(app_name, context_path, + dockerfile_path=os.path.relpath(dockerfile_path, context_path)) + + static_dockerfiles = find_dockerfiles_paths(os.path.join(root_path, STATIC_IMAGES_PATH)) + static_images = [] + for dockerfile_path in static_dockerfiles: + context_path = os.path.relpath(dockerfile_path, output_path) + app_name = app_name_from_path(os.path.basename(context_path)) + static_images.append(app_name) + artifacts[app_name] = build_artifact(app_name, context_path, base_images) + + app_dockerfiles = find_dockerfiles_paths(apps_path) + + for dockerfile_path in app_dockerfiles: + app_relative_to_skaffold = os.path.relpath(dockerfile_path, output_path) + context_path = os.path.relpath(dockerfile_path, '.') + app_relative_to_base = os.path.relpath(dockerfile_path, apps_path) + app_name = app_name_from_path(app_relative_to_base) + app_key = app_name.replace('-', '_') + if app_key not in apps: + if 'tasks' in app_relative_to_base and manage_task_images: + parent_app_name = app_name_from_path(app_relative_to_base.split('/tasks')[0]) + parent_app_key = parent_app_name.replace('-', '_') + + if parent_app_key in apps: + artifacts[app_key] = build_artifact(app_name, app_relative_to_skaffold, + base_images + static_images) + + continue + + build_requirements = apps[app_key][KEY_HARNESS]['dependencies'].get('build', []) + artifacts[app_key] = build_artifact(app_name, app_relative_to_skaffold, build_requirements) + + app = apps[app_key] + if app[KEY_HARNESS][KEY_DEPLOYMENT]['image']: + release_config['artifactOverrides']['apps'][app_key] = \ + { + 'harness': { + 'deployment': { + 'image': app[KEY_HARNESS]['name'] + } + } + } + + flask_main = find_file_paths(context_path, '__main__.py') + + if flask_main: + release_config['overrides']['apps'][app_key] = \ + { + 'harness': { + 'deployment': { + 'command': ['python'], + 'args': [f'/usr/src/app/{os.path.basename(flask_main[0])}/__main__.py'] + } + } + } + + skaffold_conf['build']['artifacts'] = [v for v in artifacts.values()] + merge_to_yaml_file(skaffold_conf, os.path.join(output_path, 'skaffold.yaml')) + + +def create_vscode_debug_configuration(root_paths, values_manual_deploy): + logging.info("Creating VS code cloud build configuration.\nCloud build extension is needed to debug.") + + vscode_launch_path = '.vscode/launch.json' + + vs_conf = get_json_template(vscode_launch_path, True) + + debug_conf = get_json_template('vscode-debug-template.json', True) + + if values_manual_deploy['registry'].get('name', None): + debug_conf["imageRegistry"] = values_manual_deploy['registry']['name'][:-1] # remove trailing / + for i in range(len(vs_conf['configurations'])): + conf = vs_conf['configurations'][i] + if conf['name'] == debug_conf['name']: + del vs_conf['configurations'][i] + break + vs_conf['configurations'].append(debug_conf) + + apps = values_manual_deploy[KEY_APPS] + + for root_path in root_paths: + apps_path = os.path.join(root_path, 'applications') + + flask_main_paths = find_file_paths(apps_path, '__main__.py') + + for path in flask_main_paths: + app_relative_to_base = os.path.relpath(os.path.dirname(path), apps_path) + app_relative_to_root = os.path.relpath(os.path.dirname(path), '.') + app_name = app_name_from_path(app_relative_to_base.split('/')[0]) + app_key = app_name.replace('-', '_') + if app_key in apps.keys(): + debug_conf["debug"].append({ + "image": app_name, + # the double source map doesn't work at the moment. Hopefully will be fixed in future skaffold updates + "sourceFileMap": { + f"${{workspaceFolder}}/{app_relative_to_root}": "/usr/src/app", + } + }) + debug_conf["debug"].append({ + "image": app_name, + "sourceFileMap": { + "${workspaceFolder}/cloud-harness/libraries": "/libraries" + } + }) + + if not os.path.exists(os.path.dirname(vscode_launch_path)): + os.makedirs(os.path.dirname(vscode_launch_path)) + with open(vscode_launch_path, 'w') as f: + json.dump(vs_conf, f, indent=2, sort_keys=True) diff --git a/utilities/cloudharness_utilities/helm.py b/utilities/cloudharness_utilities/helm.py index b3ae2dd5..a14db89c 100644 --- a/utilities/cloudharness_utilities/helm.py +++ b/utilities/cloudharness_utilities/helm.py @@ -4,12 +4,10 @@ import yaml import os import shutil -import sys import logging import subprocess import tarfile from docker import from_env as DockerClient -from pathlib import Path from .constants import VALUES_MANUAL_PATH, VALUE_TEMPLATE_PATH, HELM_CHART_PATH, APPS_PATH, HELM_PATH, HERE, \ DEPLOYMENT_CONFIGURATION_PATH from .utils import get_cluster_ip, get_image_name, env_variable, get_sub_paths, app_name_from_path, \ @@ -17,22 +15,38 @@ KEY_HARNESS = 'harness' KEY_SERVICE = 'service' +KEY_DATABASE = 'database' KEY_DEPLOYMENT = 'deployment' KEY_APPS = 'apps' +def deploy(namespace, output_path='./deployment'): + helm_path = os.path.join(output_path, HELM_CHART_PATH) + logging.info('Deploying helm chart %s', helm_path) + subprocess.run("helm dependency update".split(), cwd=helm_path) + + subprocess.run( + f"helm upgrade {namespace} {helm_path} -n {namespace} --install --reset-values".split()) + + def create_helm_chart(root_paths, tag='latest', registry='', local=True, domain=None, exclude=(), secured=True, - output_path='./deployment', include=None, registry_secret=None, tls=True): + output_path='./deployment', include=None, registry_secret=None, tls=True, env=None, + namespace=None): """ Creates values file for the helm chart """ - dest_deployment_path = os.path.join(output_path, HELM_CHART_PATH) + assert domain, 'A domain must be specified' + dest_deployment_path = os.path.join(output_path, HELM_CHART_PATH) + if registry and registry[-1] != '/': + registry = registry + '/' if os.path.exists(dest_deployment_path): shutil.rmtree(dest_deployment_path) # Initialize with default copy_merge_base_deployment(dest_deployment_path, os.path.join(HERE, DEPLOYMENT_CONFIGURATION_PATH, HELM_PATH)) - helm_values = collect_helm_values(HERE, tag=tag, registry=registry, exclude=exclude, include=include) + helm_values = get_template(os.path.join(HERE, DEPLOYMENT_CONFIGURATION_PATH, HELM_PATH, 'values.yaml')) + helm_values = dict_merge(helm_values, + collect_helm_values(HERE, tag=tag, registry=registry, exclude=exclude, env=env)) # Override for every cloudharness scaffolding for root_path in root_paths: @@ -41,18 +55,54 @@ def create_helm_chart(root_paths, tag='latest', registry='', local=True, domain= collect_apps_helm_templates(root_path, exclude=exclude, include=include, dest_helm_chart_path=dest_deployment_path) helm_values = dict_merge(helm_values, - collect_helm_values(root_path, tag=tag, registry=registry, exclude=exclude, - include=include)) + collect_helm_values(root_path, tag=tag, registry=registry, exclude=exclude, env=env)) + + # Override for every cloudharness scaffolding + helm_values[KEY_APPS] = {} + + for root_path in root_paths: + app_values = init_app_values(root_path, exclude=exclude, values=helm_values[KEY_APPS]) + helm_values[KEY_APPS] = dict_merge(helm_values[KEY_APPS], + app_values) + + # Override for every cloudharness scaffolding + for root_path in root_paths: + app_values = collect_app_values(root_path, tag=tag, registry=registry, exclude=exclude, env=env) + helm_values[KEY_APPS] = dict_merge(helm_values[KEY_APPS], + app_values) create_tls_certificate(local, domain, tls, output_path, helm_values) - finish_helm_values(values=helm_values, tag=tag, registry=registry, local=local, domain=domain, secured=secured, - registry_secret=registry_secret, tls=tls) + values, include = finish_helm_values(values=helm_values, namespace=namespace, tag=tag, registry=registry, + local=local, domain=domain, + secured=secured, + registry_secret=registry_secret, tls=tls, include=include) + + for root_path in root_paths: + collect_apps_helm_templates(root_path, exclude=exclude, include=include, + dest_helm_chart_path=dest_deployment_path) # Save values file for manual helm chart merged_values = merge_to_yaml_file(helm_values, os.path.join(dest_deployment_path, VALUES_MANUAL_PATH)) + if namespace: + merge_to_yaml_file({'metadata': {'namespace': namespace}}, os.path.join(dest_deployment_path, 'Chart.yaml')) return merged_values +def get_included_with_dependencies(values, include): + app_values = values['apps'].values() + directly_included = [app for app in app_values if any(inc == app['harness']['name'] for inc in include)] + + dependent = set(include) + for app in directly_included: + dependent.update(set(app['harness']['dependencies']['hard'])) + dependent.update(set(app['harness']['dependencies']['soft'])) + if values['secured_gatekeepers'] and app['harness']['secured']: + dependent.add('accounts') + if len(dependent) == len(include): + return dependent + return get_included_with_dependencies(values, dependent) + + def merge_helm_chart(source_templates_path, dest_helm_chart_path=HELM_CHART_PATH): pass @@ -87,9 +137,19 @@ def collect_apps_helm_templates(search_root, dest_helm_chart_path, exclude=(), i dest_dir = os.path.join(dest_helm_chart_path, 'resources', app_name) logging.info("Collecting resources for application %s to %s", app_name, dest_dir) + + merge_configuration_directories(resources_dir, dest_dir) + + subchart_dir = os.path.join(app_path, 'deploy/charts') + if os.path.exists(subchart_dir): + dest_dir = os.path.join(dest_helm_chart_path, 'charts', app_name) + + logging.info("Collecting templates for application %s to %s", app_name, dest_dir) if os.path.exists(dest_dir): - shutil.rmtree(dest_dir) - shutil.copytree(resources_dir, dest_dir) + logging.warning("Merging/overriding all files in directory %s", dest_dir) + merge_configuration_directories(subchart_dir, dest_dir) + else: + shutil.copytree(subchart_dir, dest_dir) def copy_merge_base_deployment(dest_helm_chart_path, base_helm_chart): @@ -103,35 +163,68 @@ def copy_merge_base_deployment(dest_helm_chart_path, base_helm_chart): shutil.copytree(base_helm_chart, dest_helm_chart_path) -def collect_helm_values(deployment_root, exclude=(), include=None, tag='latest', registry=''): +def collect_helm_values(deployment_root, exclude=(), tag='latest', registry='', env=None): """ Creates helm values from a cloudharness deployment scaffolding """ values_template_path = os.path.join(deployment_root, DEPLOYMENT_CONFIGURATION_PATH, 'values-template.yaml') - value_spec_template_path = os.path.join(deployment_root, DEPLOYMENT_CONFIGURATION_PATH, 'value-template.yaml') - if not os.path.exists(values_template_path): - values = {} - else: - values = get_template(values_template_path) - values[KEY_APPS] = {} + values = get_template(values_template_path) + if env is not None: + specific_template_path = os.path.join(deployment_root, DEPLOYMENT_CONFIGURATION_PATH, + f'values-template-{env}.yaml') + if os.path.exists(specific_template_path): + logging.info("Specific environment values template found: " + specific_template_path) + with open(specific_template_path) as f: + values_env_specific = yaml.safe_load(f) + values = dict_merge(values, values_env_specific) + return values + + +def init_app_values(deployment_root, exclude, values={}): app_base_path = os.path.join(deployment_root, APPS_PATH) + overridden_template_path = os.path.join(deployment_root, DEPLOYMENT_CONFIGURATION_PATH, 'value-template.yaml') + default_values_path = os.path.join(HERE, DEPLOYMENT_CONFIGURATION_PATH, 'value-template.yaml') + for app_path in get_sub_paths(app_base_path): + app_name = app_name_from_path(os.path.relpath(app_path, app_base_path)) - if app_name in exclude or (include and not any(inc in app_name for inc in include)): + if app_name in exclude: continue + app_key = app_name.replace('-', '_') + if app_key not in values: + default_values = get_template(default_values_path) + values[app_key] = default_values + overridden_defaults = get_template(overridden_template_path) + values[app_key] = dict_merge(values[app_key], overridden_defaults) + + return values - app_values = create_values_spec(app_name, app_path, tag=tag, registry=registry, - template_path=value_spec_template_path) - values[KEY_APPS][app_name.replace('-', '_')] = app_values + +def collect_app_values(deployment_root, exclude=(), tag='latest', registry='', env=None): + app_base_path = os.path.join(deployment_root, APPS_PATH) + + values = {} + for app_path in get_sub_paths(app_base_path): + app_name = app_name_from_path(os.path.relpath(app_path, app_base_path)) + + if app_name in exclude: + continue + app_key = app_name.replace('-', '_') + + app_values = create_values_spec(app_name, app_path, tag=tag, registry=registry, env=env) + + values[app_key] = dict_merge(values[app_key], app_values) if app_key in values else app_values return values -def finish_helm_values(values, tag='latest', registry='', local=True, domain=None, secured=True, registry_secret=None, tls=True): +def finish_helm_values(values, namespace, tag='latest', registry='', local=True, domain=None, secured=True, + registry_secret=None, + tls=True, include=None): """ Sets default overridden values """ @@ -144,6 +237,8 @@ def finish_helm_values(values, tag='latest', registry='', local=True, domain=Non values['registry']['name'] = registry values['registry']['secret'] = registry_secret values['tag'] = tag + if namespace: + values['namespace'] = namespace values['secured_gatekeepers'] = secured values['ingress']['ssl_redirect'] = values['ingress']['ssl_redirect'] and tls @@ -156,10 +251,47 @@ def finish_helm_values(values, tag='latest', registry='', local=True, domain=Non values['localIp'] = get_cluster_ip() except subprocess.TimeoutExpired: logging.warning("Minikube not available") + except: + logging.warning("Kubectl not available") + + apps = values[KEY_APPS] + + for app_key in apps: + v = apps[app_key] - # Create environment variables + values_from_legacy(v) + assert KEY_HARNESS in v, 'Default app value loading is broken' + + harness = v[KEY_HARNESS] + if KEY_SERVICE not in harness: + harness[KEY_SERVICE] = {} + if KEY_DEPLOYMENT not in harness: + harness[KEY_DEPLOYMENT] = {} + if KEY_DATABASE not in harness: + harness[KEY_DATABASE] = {} + app_name = app_key.replace('_', '-') + + harness['name'] = app_name + if not harness[KEY_SERVICE].get('name', None): + harness[KEY_SERVICE]['name'] = app_name + if not harness[KEY_DEPLOYMENT].get('name', None): + harness[KEY_DEPLOYMENT]['name'] = app_name + if not harness[KEY_DATABASE].get('name', None): + harness[KEY_DATABASE]['name'] = app_name.strip() + '-db' + if not harness[KEY_DEPLOYMENT].get('image', None): + harness[KEY_DEPLOYMENT]['image'] = registry + get_image_name(app_name) + f':{tag}' if tag else '' + values_set_legacy(v) + + if include: + include = get_included_with_dependencies(values, set(include)) + logging.info('Selecting included applications') + + for v in [v for v in apps]: + if apps[v]['harness']['name'] not in include: + del apps[v] + # Create environment variables create_env_variables(values) - return values + return values, include def values_from_legacy(values): @@ -192,45 +324,32 @@ def values_set_legacy(values): values['image'] = harness[KEY_DEPLOYMENT]['image'] values['name'] = harness['name'] - if harness[KEY_DEPLOYMENT]['port']: + if harness[KEY_DEPLOYMENT].get('port', None): values['port'] = harness[KEY_DEPLOYMENT]['port'] - values['resources'] = harness[KEY_DEPLOYMENT]['resources'] + if 'resources' in harness[KEY_DEPLOYMENT]: + values['resources'] = harness[KEY_DEPLOYMENT]['resources'] -def create_values_spec(app_name, app_path, tag=None, registry='', template_path=VALUE_TEMPLATE_PATH): +def create_values_spec(app_name, app_path, tag=None, registry='', env=None): logging.info('Generating values script for ' + app_name) - values_default = get_template(template_path) - specific_template_path = os.path.join(app_path, 'deploy', 'values.yaml') if os.path.exists(specific_template_path): logging.info("Specific values template found: " + specific_template_path) - with open(specific_template_path) as f: - values_specific = yaml.safe_load(f) - values = dict_merge(values_default, values_specific) + values = get_template(specific_template_path) else: - values = values_default - - values_from_legacy(values) - harness = values[KEY_HARNESS] - - if not harness['name']: - harness['name'] = app_name - if not harness[KEY_SERVICE]['name']: - harness[KEY_SERVICE]['name'] = app_name - if not harness[KEY_DEPLOYMENT]['name']: - harness[KEY_DEPLOYMENT]['name'] = app_name - if not harness[KEY_DEPLOYMENT]['image']: - if registry and registry[-1] != '/': - registry = registry + '/' - harness[KEY_DEPLOYMENT]['image'] = registry + get_image_name(app_name) + f':{tag}' if tag else '' - - values_set_legacy(values) - - for k in values: - if isinstance(values[k], dict) and KEY_HARNESS in values[k]: - values[k][KEY_HARNESS] = dict_merge(values[k][KEY_HARNESS], values_default[KEY_HARNESS]) + values = {} + if env is not None: + specific_template_path = os.path.join(app_path, 'deploy', f'values-{env}.yaml') + if os.path.exists(specific_template_path): + logging.info("Specific environment values template found: " + specific_template_path) + with open(specific_template_path) as f: + values_env_specific = yaml.safe_load(f) + values = dict_merge(values, values_env_specific) + if KEY_HARNESS in values and 'name' in values[KEY_HARNESS] and values[KEY_HARNESS]['name']: + logging.warning('Name is automatically set in applications: name %s will be ignored', + values[KEY_HARNESS]['name']) return values @@ -266,29 +385,28 @@ def hosts_info(values): logging.warning('Cannot get cluster ip') return logging.info( - "\nTo test locally, update your hosts file" + f"\n{ip}\t{' '.join(sd + '.' + domain for sd in subdomains)}") + "\nTo test locally, update your hosts file" + f"\n{ip}\t{domain + ' ' + ' '.join(sd + '.' + domain for sd in subdomains)}") deployments = (app[KEY_HARNESS][KEY_DEPLOYMENT]['name'] for app in values[KEY_APPS].values() if KEY_HARNESS in app) logging.info("\nTo run locally some apps, also those references may be needed") for appname in values[KEY_APPS]: - app = values[KEY_APPS][appname] - if 'name' not in app or 'port' not in app: continue + app = values[KEY_APPS][appname]['harness'] + if 'deployment' not in app: continue print( "kubectl port-forward -n {namespace} deployment/{app} {port}:{port}".format( - app=appname, port=app['port'], namespace=namespace)) + app=app['deployment']['name'], port=app['deployment']['port'], namespace=namespace)) print(f"127.0.0.1\t{' '.join(s + '.cloudharness' for s in deployments)}") def create_tls_certificate(local, domain, tls, output_path, helm_values): - if not tls: helm_values['tls'] = None return - helm_values['tls'] = domain.replace(".", "-") + "-tls" if not local: return + helm_values['tls'] = domain.replace(".", "-") + "-tls" HERE = os.path.dirname(os.path.realpath(__file__)).replace(os.path.sep, '/') ROOT = os.path.dirname(os.path.dirname(HERE)).replace(os.path.sep, '/') diff --git a/utilities/cloudharness_utilities/openapi.py b/utilities/cloudharness_utilities/openapi.py index 276e7841..a0720dbf 100644 --- a/utilities/cloudharness_utilities/openapi.py +++ b/utilities/cloudharness_utilities/openapi.py @@ -7,26 +7,31 @@ import glob import urllib.request from cloudharness_utilities import HERE +from cloudharness_utilities.utils import copymergedir, replaceindir, movedircontent, replace_in_file, to_python_module import logging CODEGEN = os.path.join(HERE, 'bin', 'openapi-generator-cli.jar') APPLICATIONS_SRC_PATH = os.path.join('applications') LIB_NAME = 'cloudharness_cli' -OPENAPI_GEN_URL = 'https://repo1.maven.org/maven2/org/openapitools/openapi-generator-cli/4.3.0/openapi-generator-cli-4.3.0.jar' +OPENAPI_GEN_URL = 'https://repo1.maven.org/maven2/org/openapitools/openapi-generator-cli/5.0.0/openapi-generator-cli-5.0.0.jar' def generate_server(app_path): + get_dependencies() openapi_dir = os.path.join(app_path, 'api') openapi_file = glob.glob(os.path.join(openapi_dir, '*.yaml'))[0] - command = f"java -jar {CODEGEN} generate -i {openapi_file} -g python-flask -o {app_path}/server -c {openapi_dir}/config.json" + out_name = f"backend" if not os.path.exists(f"{app_path}/server") else f"server" + out_path = f"{app_path}/{out_name}" + command = f"java -jar {CODEGEN} generate -i {openapi_file} -g python-flask -o {out_path} -c {openapi_dir}/config.json" os.system(command) def generate_python_client(module, openapi_file, client_src_path, lib_name=LIB_NAME): + get_dependencies() config_path = os.path.join(os.path.dirname(openapi_file), 'config.json') - module = module.replace('-', '_') + module = to_python_module(module) with open(config_path, 'w') as f: f.write(json.dumps(dict(packageName=f"{lib_name}.{module}"))) command = f"java -jar {CODEGEN} generate " \ @@ -37,6 +42,18 @@ def generate_python_client(module, openapi_file, client_src_path, lib_name=LIB_N os.system(command) +def generate_ts_client(openapi_file): + config_path = os.path.join(os.path.dirname(openapi_file), 'config.json') + out_dir = f"{os.path.dirname(os.path.dirname(openapi_file))}/frontend/src/rest" + command = f"java -jar {CODEGEN} generate " \ + f"-i {openapi_file} " \ + f"-g typescript-axios " \ + f"-o {out_dir}" + os.system(command) + + replaceindir(out_dir, "http://localhost", '') + + def get_dependencies(): """ Checks if java is installed @@ -50,7 +67,7 @@ def get_dependencies(): sys.exit('java not found') if not os.path.exists(CODEGEN): - logging.warning("Code generator client not found \n") + logging.warning("Code generator client not found: downloading \n") cdir = os.path.dirname(CODEGEN) if not os.path.exists(cdir): os.makedirs(cdir) diff --git a/utilities/cloudharness_utilities/utils.py b/utilities/cloudharness_utilities/utils.py index 0afb13ba..566bc6e7 100644 --- a/utilities/cloudharness_utilities/utils.py +++ b/utilities/cloudharness_utilities/utils.py @@ -1,13 +1,19 @@ import glob import subprocess import os +import json import collections import oyaml as yaml import shutil import logging +import fileinput from .constants import HERE, NEUTRAL_PATHS, DEPLOYMENT_CONFIGURATION_PATH, BASE_IMAGES_PATH, STATIC_IMAGES_PATH, \ - APPS_PATH, BUILD_FILENAMES + APPS_PATH, BUILD_FILENAMES, EXCLUDE_PATHS + +REPLACE_TEXT_FILES_EXTENSIONS = ( + '.js', '.md', '.py', '.js', '.ts', '.tsx', '.txt', 'Dockerfile', 'yaml', 'json', '.ejs' +) def app_name_from_path(dockerfile_path): @@ -18,9 +24,13 @@ def get_sub_paths(base_path): return tuple(path for path in glob.glob(base_path + "/*") if os.path.isdir(path)) -def find_dockerfiles_paths(base_directory): +def find_file_paths(base_directory, file_name): return tuple(os.path.dirname(path).replace(os.path.sep, "/") for path in - glob.glob(f"{base_directory}/**/Dockerfile", recursive=True)) + glob.glob(f"{base_directory}/**/{file_name}", recursive=True)) + + +def find_dockerfiles_paths(base_directory): + return find_file_paths(base_directory, 'Dockerfile') def get_parent_app_name(app_relative_path): @@ -28,11 +38,7 @@ def get_parent_app_name(app_relative_path): def get_image_name(app_name, base_name=None): - return base_name + '-' + app_name if base_name else app_name - - -def get_image_name_from_dockerfile_path(self, dockerfile_path, base_name): - return get_image_name(os.path.basename(os.path.dirname(dockerfile_path)), base_name) + return base_name + '/' + app_name if base_name else app_name def env_variable(name, value): @@ -41,57 +47,168 @@ def env_variable(name, value): def get_cluster_ip(): out = subprocess.check_output(['kubectl', 'cluster-info'], timeout=10).decode("utf-8") - print(type(out)) ip = out.split('\n')[0].split('://')[1].split(':')[0] return ip -def get_template(yaml_path): - with open(os.path.join(HERE, DEPLOYMENT_CONFIGURATION_PATH, os.path.basename(yaml_path))) as f: - dict_template = yaml.safe_load(f) +def robust_load_json(json_path): + """ + Supports json with // comments + """ + try: + with open(json_path) as f: + return json.load(f) + except: + with open(json_path) as f: + return json.loads("".join(line for line in f if "//" not in line)) + + +def get_json_template(json_path, base_default=False): + default_template_path = os.path.join(HERE, DEPLOYMENT_CONFIGURATION_PATH, os.path.basename(json_path)) + dict_template = {} + if base_default and os.path.exists(default_template_path): + dict_template = robust_load_json(default_template_path) + if os.path.exists(json_path): + override_tpl = robust_load_json(json_path) + if override_tpl: + dict_template = dict_merge(dict_template or {}, override_tpl) + return dict_template or {} + + +def get_template(yaml_path, base_default=False): + default_template_path = os.path.join(HERE, DEPLOYMENT_CONFIGURATION_PATH, os.path.basename(yaml_path)) + dict_template = {} + if base_default and os.path.exists(default_template_path): + with open(default_template_path) as f: + dict_template = yaml.safe_load(f) if os.path.exists(yaml_path): with open(yaml_path) as f: override_tpl = yaml.safe_load(f) if override_tpl: - dict_template = dict_merge(dict_template, override_tpl) - return dict_template + dict_template = dict_merge(dict_template or {}, override_tpl) + return dict_template or {} def file_is_yaml(fname): return fname[-4:] == 'yaml' or fname[-3:] == 'yml' +def replaceindir(root_src_dir, source, replace): + """ + Does copy and merge (shutil.copytree requires that the destination does not exist) + :param root_src_dir: + :param root_dst_dir: + :return: + """ + logging.info('Replacing in directory %s to %s', source, replace) + for src_dir, dirs, files in os.walk(root_src_dir): + if any(path in src_dir for path in EXCLUDE_PATHS): + continue + + for dirname in dirs: + if source in dirname: + dirpath = os.path.join(src_dir, dirname) + movedircontent(dirpath, dirpath.replace(source, to_python_module(replace))) + + for src_dir, dirs, files in os.walk(root_src_dir): + for file_ in files: + if not any(file_.endswith(ext) for ext in REPLACE_TEXT_FILES_EXTENSIONS): + continue + + src_file = os.path.join(src_dir, file_) + replace_in_file(src_file, source, replace) + + +def replace_in_file(src_file, source, replace): + if src_file.endswith('.py') or os.path.basename(src_file) == 'Dockerfile': + replace = to_python_module(replace) + with fileinput.FileInput(src_file, inplace=True) as file: + try: + for line in file: + print(line.replace(source, replace), end='') + except UnicodeDecodeError: + pass + + +def copymergedir(root_src_dir, root_dst_dir): + """ + Does copy and merge (shutil.copytree requires that the destination does not exist) + :param root_src_dir: + :param root_dst_dir: + :return: + """ + logging.info('Copying directory %s to %s', root_src_dir, root_dst_dir) + for src_dir, dirs, files in os.walk(root_src_dir): + + dst_dir = src_dir.replace(root_src_dir, root_dst_dir, 1) + if not os.path.exists(dst_dir): + os.makedirs(dst_dir) + for file_ in files: + src_file = os.path.join(src_dir, file_) + dst_file = os.path.join(dst_dir, file_) + if os.path.exists(dst_file): + os.remove(dst_file) + try: + shutil.copy(src_file, dst_dir) + except: + logging.warning("Error copying file %s to %s.", src_file, dst_dir) + + +def movedircontent(root_src_dir, root_dst_dir): + """ + Does copy and merge (shutil.copytree requires that the destination does not exist) + :param root_src_dir: + :param root_dst_dir: + :return: + """ + logging.info('Moving directory content from %s to %s', root_src_dir, root_dst_dir) + for src_dir, dirs, files in os.walk(root_src_dir): + dst_dir = src_dir.replace(root_src_dir, root_dst_dir, 1) + if not os.path.exists(dst_dir): + os.makedirs(dst_dir) + for file_ in files: + src_file = os.path.join(src_dir, file_) + dst_file = os.path.join(dst_dir, file_) + + try: + shutil.move(src_file, os.path.join(dst_dir, os.path.basename(src_file))) + except: + logging.warning("Error moving file %s to %s.", src_file, dst_dir, exc_info=True) + shutil.rmtree(root_src_dir) + + def merge_configuration_directories(source, dest): if not os.path.exists(source): return if not os.path.exists(dest): - shutil.copytree(source, dest) + shutil.copytree(source, dest, ignore=shutil.ignore_patterns(*EXCLUDE_PATHS)) return - for fname in glob.glob(source + "/*"): - frel = os.path.relpath(fname, start=source) - fdest = os.path.join(dest, frel) - - if os.path.basename(fname) in BUILD_FILENAMES: - continue - - if os.path.isdir(fname): - merge_configuration_directories(fname, fdest) + for src_dir, dirs, files in os.walk(source): + if any(path in src_dir for path in EXCLUDE_PATHS): continue - - if not os.path.exists(fdest): - shutil.copy2(fname, fdest) - elif file_is_yaml(fname): - - try: - merge_yaml_files(fname, fdest) - logging.info(f"Merged/overridden file content of {fdest} with {fname}") - except yaml.YAMLError as e: - logging.warning(f"Overwriting file {fdest} with {fname}") - shutil.copy2(fname, fdest) - else: - logging.warning(f"Overwriting file {fdest} with {fname}") - shutil.copy2(fname, fdest) + dst_dir = src_dir.replace(source, dest, 1) + if not os.path.exists(dst_dir): + os.makedirs(dst_dir) + for fname in files: + if fname in BUILD_FILENAMES: + continue + fpath = os.path.join(src_dir, fname) + frel = os.path.relpath(fpath, start=source) + fdest = os.path.join(dest, frel) + if not os.path.exists(fdest): + shutil.copy2(fpath, fdest) + elif file_is_yaml(fpath): + + try: + merge_yaml_files(fpath, fdest) + logging.info(f"Merged/overridden file content of {fdest} with {fpath}") + except yaml.YAMLError as e: + logging.warning(f"Overwriting file {fdest} with {fpath}") + shutil.copy2(fpath, fdest) + else: + logging.warning(f"Overwriting file {fdest} with {fpath}") + shutil.copy2(fpath, fdest) def merge_yaml_files(fname, fdest): @@ -179,4 +296,8 @@ def merge_app_directories(root_paths, destination) -> None: merge_configuration_directories(os.path.join(rpath, 'client'), os.path.join(destination, 'client')) merge_configuration_directories(os.path.join(rpath, 'deployment-configuration'), - os.path.join(destination, 'deployment-configuration')) \ No newline at end of file + os.path.join(destination, 'deployment-configuration')) + + +def to_python_module(name): + return name.replace('-', '_') diff --git a/utilities/harness-application b/utilities/harness-application index b5daec5e..68e34962 100644 --- a/utilities/harness-application +++ b/utilities/harness-application @@ -3,12 +3,19 @@ import sys import os import shutil +import re from cloudharness_utilities import HERE +from cloudharness_utilities.constants import APPLICATION_TEMPLATE_PATH import cloudharness_utilities.openapi -from cloudharness_utilities.openapi import generate_server, APPLICATIONS_SRC_PATH +from cloudharness_utilities.openapi import generate_server, APPLICATIONS_SRC_PATH, generate_ts_client +from cloudharness_utilities.utils import merge_configuration_directories, replaceindir, replace_in_file, \ + to_python_module -APPLICATION_TEMPLATE = os.path.join(HERE, 'application-template') +# Only allow lowercased alphabetical characters separated by "-". +name_pattern = re.compile("[a-z]+((-)?[a-z])?") + +PLACEHOLDER = '__APP_NAME__' if __name__ == "__main__": import argparse @@ -17,15 +24,46 @@ if __name__ == "__main__": description='Creates a new Application.') parser.add_argument('name', metavar='name', type=str, help='Application name') + parser.add_argument('-t', '--template', dest='templates', action="append", default=['base', 'server'], + help="""Add a template name. + + Available templates: + - base (backend flask app based on openapi, always included) + - webapp (webapp including backend and frontend) + - db-postgres + - db-neo4j + - db-mongo + """) args, unknown = parser.parse_known_args(sys.argv[1:]) if unknown: print('There are unknown args. Make sure to call the script with the accepted args. Try --help') print(f'unknown: {unknown}') - else: - app_path = os.path.join(APPLICATIONS_SRC_PATH, args.name) - shutil.copytree(APPLICATION_TEMPLATE, app_path) # TODO replace the name inside the template - generate_server(app_path) + exit(1) + + try: + match = name_pattern.match(args.name) + if not match: + print("Invalid application name") + print( + f"Application name must start and end with lowercased alphabetical characters and may contain '-' as separator. Used expression: '{name_pattern.pattern}'") + exit(1) + except re.error: + print("Invalid regex") + exit(1) + app_path = os.path.join(APPLICATIONS_SRC_PATH, args.name) + for template_name in args.templates: + if template_name == 'server': + generate_server(app_path) + for base_path in (HERE, os.getcwd()): + template_path = os.path.join(base_path, APPLICATION_TEMPLATE_PATH, template_name) + if os.path.exists(template_path): + merge_configuration_directories(template_path, app_path) + replace_in_file(os.path.join(app_path, 'api/config.json'), PLACEHOLDER, to_python_module(args.name)) + replaceindir(app_path, PLACEHOLDER, args.name) + if 'webapp' in args.templates: + os.remove(os.path.join(app_path, 'backend', 'Dockerfile')) + generate_ts_client(openapi_file=os.path.join(app_path, 'api/openapi.yaml')) diff --git a/utilities/harness-codefresh b/utilities/harness-codefresh deleted file mode 100644 index a58fb841..00000000 --- a/utilities/harness-codefresh +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env python - -import sys -import os - -from cloudharness_utilities.codefresh import create_codefresh_deployment_scripts -from cloudharness_utilities.helm import create_helm_chart - - -HERE = os.path.dirname(os.path.realpath(__file__)).replace(os.path.sep, '/') -ROOT = os.path.dirname(HERE).replace(os.path.sep, '/') - -if __name__ == "__main__": - import argparse - - parser = argparse.ArgumentParser( - description='Walk filesystem inside ./applications and define build and deploy scripts.') - parser.add_argument('paths', metavar='paths', default=[ROOT], type=str, nargs='*', - help='Base paths to start looking for applications. The paths will be processed ' - 'in the given order so determining the build and overriding precedence.') - parser.add_argument('-i', '--include', dest='include', action="append", default=[], - help='Specify the applications to include and exclude the rest. ' - 'Omit to build images for all Docker files.') - - args, unknown = parser.parse_known_args(sys.argv[1:]) - - if unknown: - print('There are unknown args. Make sure to call the script with the accepted args. Try --help') - print(f'unknown: {unknown}') - else: - create_codefresh_deployment_scripts(args.paths, include=args.include) - diff --git a/utilities/harness-deployment b/utilities/harness-deployment index b20ef64b..9acd9fa2 100644 --- a/utilities/harness-deployment +++ b/utilities/harness-deployment @@ -5,7 +5,8 @@ import os from cloudharness_utilities.build import Builder from cloudharness_utilities.utils import merge_app_directories -from cloudharness_utilities.helm import create_helm_chart, hosts_info +from cloudharness_utilities.helm import create_helm_chart, hosts_info, deploy +from cloudharness_utilities.dev_utils import create_skaffold_configuration, create_vscode_debug_configuration from cloudharness_utilities.codefresh import create_codefresh_deployment_scripts HERE = os.path.dirname(os.path.realpath(__file__)).replace(os.path.sep, '/') @@ -28,8 +29,8 @@ if __name__ == "__main__": parser.add_argument('-t', '--tag', dest='tag', action="store", default='latest', help='Add a tag with the current version (default `latest`)') - parser.add_argument('-n', '--namespace', dest='namespace', action="store", default='default', - help='Specify the namespace of the deployment (default `default`)') + parser.add_argument('-n', '--namespace', dest='namespace', action="store", default=None, + help='Specify the namespace of the deployment (default taken from values.yaml)') parser.add_argument('-r', '--registry', dest='registry', action="store", default='', help='Specify image registry prefix') @@ -48,14 +49,17 @@ if __name__ == "__main__": help='Specify for local deployments info and setup') parser.add_argument('-u', '--disable-security', dest='unsecured', action="store_true", help='Disable secured gatekeepers access') - parser.add_argument('-e', '--exclude', dest='exclude', action="append", default=(), + parser.add_argument('-ex', '--exclude', dest='exclude', action="append", default=[], + help='Specify application to exclude from the deployment') + parser.add_argument('-e', '--env', dest='env', action="store", default=None, help='Specify application to exclude from the deployment') - parser.add_argument('-m', '--merge', dest='merge', action="store", default=None, help='Merge application folders and build in the given directory') parser.add_argument('-dtls', '--disable-tls', dest='no_tls', action="store_true", help='Disable tls (serve on http)') + parser.add_argument('--deploy', dest='deploy', action="store_true", + help='Deploy helm chart') args, unknown = parser.parse_known_args(sys.argv[1:]) @@ -65,14 +69,9 @@ if __name__ == "__main__": print(f'unknown: {unknown}') else: - builder = Builder(root_paths, args.include, tag=args.tag, registry=args.registry, interactive=args.build_interactive, - exclude=args.exclude, namespace=args.namespace, domain=args.domain) - if args.merge: - merge_app_directories(builder.root_paths, destination=args.merge) - builder.root_paths = [args.merge] - if args.build or args.build_interactive: - builder.run() + merge_app_directories(root_paths, destination=args.merge) + root_paths = [args.merge] values_manual_deploy = create_helm_chart( root_paths, @@ -85,7 +84,32 @@ if __name__ == "__main__": exclude=args.exclude, include=args.include, registry_secret=args.registry_secret, - tls=not args.no_tls + tls=not args.no_tls, + env=args.env, + namespace=args.namespace ) - create_codefresh_deployment_scripts(builder.root_paths, include=args.include) + + build_included = [app['harness']['name'] for app in values_manual_deploy['apps'].values() if 'harness' in app] + + create_codefresh_deployment_scripts(root_paths, include=build_included) # LEGACY + create_codefresh_deployment_scripts(root_paths, include=build_included, + template_name='codefresh-template-dev.yaml', + out_filename="codefresh-dev.yaml") + create_codefresh_deployment_scripts(root_paths, include=build_included, + template_name='codefresh-template-prod.yaml', + out_filename="codefresh-prod.yaml") + + create_skaffold_configuration(root_paths, values_manual_deploy) + create_vscode_debug_configuration([os.path.join(os.getcwd(), path) for path in args.paths], + values_manual_deploy) + + if args.build or args.build_interactive: + builder = Builder(root_paths, build_included, tag=args.tag, registry=args.registry, + interactive=args.build_interactive, + exclude=args.exclude, namespace=args.namespace, domain=args.domain) + builder.run() + hosts_info(values_manual_deploy) + + if args.deploy: + deploy(args.namespace, args.output_path) diff --git a/utilities/harness-generate b/utilities/harness-generate index df835871..07fe985b 100644 --- a/utilities/harness-generate +++ b/utilities/harness-generate @@ -6,7 +6,9 @@ import shutil import sys import logging -from cloudharness_utilities.openapi import LIB_NAME, generate_python_client, generate_server, get_dependencies +from cloudharness_utilities.openapi import LIB_NAME, generate_python_client, generate_server, get_dependencies, \ + generate_ts_client +from cloudharness_utilities.utils import copymergedir HERE = os.path.dirname(os.path.realpath(__file__)) ROOT = os.path.dirname(HERE) @@ -16,43 +18,21 @@ def get_openapi_file_paths(root_path): return [path for path in glob.glob(root_path + '/applications/*/api/*.yaml')] -def get_modules(openapi_files): +def get_application_paths(openapi_files): return [os.path.basename(os.path.dirname(os.path.dirname(path))) for path in openapi_files] -def generate_servers(root_path): +def generate_servers(root_path, interactive=False): """ Generates server stubs """ openapi_files = get_openapi_file_paths(root_path) - modules = get_modules(openapi_files) + modules = get_application_paths(openapi_files) for i in range(len(modules)): - openapi_file = openapi_files[i] - application_root = os.path.dirname(os.path.dirname(openapi_file)) - generate_server(application_root) - - -def copymergedir(root_src_dir, root_dst_dir): - """ - Does copy and merge (shutil.copytree requires that the destination does not exist) - :param root_src_dir: - :param root_dst_dir: - :return: - """ - logging.info('Copying directory %s to %s', root_src_dir, root_dst_dir) - for src_dir, dirs, files in os.walk(root_src_dir): - dst_dir = src_dir.replace(root_src_dir, root_dst_dir, 1) - if not os.path.exists(dst_dir): - os.makedirs(dst_dir) - for file_ in files: - src_file = os.path.join(src_dir, file_) - dst_file = os.path.join(dst_dir, file_) - if os.path.exists(dst_file): - os.remove(dst_file) - try: - shutil.copy(src_file, dst_dir) - except: - logging.warning("Error copying file %s to %s.", src_file, dst_dir) + if not interactive or input("Do you want to generate " + openapi_files[i] + "? [Y/n]").upper() != 'N': + openapi_file = openapi_files[i] + application_root = os.path.dirname(os.path.dirname(openapi_file)) + generate_server(application_root) def aggregate_packages(client_src_path, lib_name=LIB_NAME): @@ -131,41 +111,44 @@ def aggregate_packages(client_src_path, lib_name=LIB_NAME): shutil.rmtree(MODULE_TMP_PATH) -def generate_clients(root_path, client_lib_name=LIB_NAME): +def generate_clients(root_path, client_lib_name=LIB_NAME, interactive=False): """ Generates client stubs """ + if interactive and input("Do you want to generate client libraries? [Y/n]").upper() == 'N': + return + openapi_files = get_openapi_file_paths(root_path) - modules = get_modules(openapi_files) - client_src_path = os.path.join(root_path, 'client', client_lib_name) - for i in range(len(modules)): - module = modules[i] + applications = get_application_paths(openapi_files) + + client_src_path = os.path.join(root_path, 'libraries/client', client_lib_name) + for i in range(len(applications)): + app_name = applications[i] openapi_file = openapi_files[i] - generate_python_client(module, openapi_file, client_src_path, lib_name=client_lib_name) + app_dir = os.path.dirname(os.path.dirname(openapi_file)) + generate_python_client(app_name, openapi_file, client_src_path, lib_name=client_lib_name) + if os.path.exists(os.path.join(app_dir, 'frontend')): + generate_ts_client(openapi_file) aggregate_packages(client_src_path, client_lib_name) if __name__ == "__main__": - import argparse parser = argparse.ArgumentParser( - description='Walk filesystem inside ./applications and define build and deploy scripts.') + description='Walk filesystem inside ./applications create application scaffolding.') parser.add_argument('path', metavar='path', default=ROOT, type=str, help='Base path of the application.') - parser.add_argument('-nc', '--no-client', dest='client', action="store_false", - help='Specify for local deployments info and setup') - parser.add_argument('-ns', '--no-server', dest='server', action="store_false", - help='Specify for local deployments info and setup') parser.add_argument('-cn', '--client-name', dest='client_name', action="store", default=LIB_NAME, help='Specify image registry prefix') + parser.add_argument('-i', '--interactive', dest='interactive', action="store_true", + help='Asks before generate') args, unknown = parser.parse_known_args(sys.argv[1:]) root_path = os.path.join(os.getcwd(), args.path) if not os.path.isabs(args.path) else args.path get_dependencies() - if args.server: - generate_servers(root_path) - if args.client: - generate_clients(root_path, args.client_name) + generate_servers(root_path, interactive=args.interactive) + + generate_clients(root_path, args.client_name, interactive=args.interactive) diff --git a/utilities/setup.py b/utilities/setup.py index d8d78e06..ff932741 100644 --- a/utilities/setup.py +++ b/utilities/setup.py @@ -12,7 +12,7 @@ NAME = "cloudharness-utilities" -VERSION = "0.2.0" +VERSION = "0.3.0" # To install the library, run the following # # python setup.py install @@ -37,7 +37,7 @@ install_requires=REQUIREMENTS, packages=find_packages(exclude=["*.tests", "*.tests.*", "tests.*", "tests"]), include_package_data=True, - scripts=['harness-codefresh', 'harness-deployment', 'harness-generate', 'harness-application'], + scripts=['harness-deployment', 'harness-generate', 'harness-application'], long_description="""\ MetaCell Neuroscience Platform - CloudHarness deploy library """ diff --git a/utilities/test-requirements.txt b/utilities/test-requirements.txt new file mode 100644 index 00000000..e2fead49 --- /dev/null +++ b/utilities/test-requirements.txt @@ -0,0 +1,8 @@ +coverage>=4.0.3 +nose>=1.3.7 +pluggy>=0.3.1 +py>=1.4.31 +randomize>=0.13 +pytest>=5.0.0 +pytest-cov +-e . diff --git a/utilities/tests/resources/applications/accounts/deploy/resources/aresource.txt b/utilities/tests/resources/applications/accounts/deploy/resources/aresource.txt new file mode 100644 index 00000000..e69de29b diff --git a/utilities/tests/resources/applications/accounts/deploy/values-dev.yaml b/utilities/tests/resources/applications/accounts/deploy/values-dev.yaml new file mode 100644 index 00000000..2b9fefa6 --- /dev/null +++ b/utilities/tests/resources/applications/accounts/deploy/values-dev.yaml @@ -0,0 +1 @@ +a: dev \ No newline at end of file diff --git a/utilities/tests/resources/applications/accounts/deploy/values.yaml b/utilities/tests/resources/applications/accounts/deploy/values.yaml new file mode 100644 index 00000000..2957614c --- /dev/null +++ b/utilities/tests/resources/applications/accounts/deploy/values.yaml @@ -0,0 +1,5 @@ +a: b +autodeploy: overridden +harness: + deployment: + port: overridden \ No newline at end of file diff --git a/utilities/tests/resources/applications/legacy/deploy/values.yaml b/utilities/tests/resources/applications/legacy/deploy/values.yaml new file mode 100644 index 00000000..2cf7ff6a --- /dev/null +++ b/utilities/tests/resources/applications/legacy/deploy/values.yaml @@ -0,0 +1,3 @@ +autodeploy: legacy +a: b +name: "I'm useless" \ No newline at end of file diff --git a/utilities/tests/resources/applications/myapp/Dockerfile b/utilities/tests/resources/applications/myapp/Dockerfile new file mode 100644 index 00000000..e69de29b diff --git a/utilities/tests/resources/applications/myapp/deploy/resources/aresource.txt b/utilities/tests/resources/applications/myapp/deploy/resources/aresource.txt new file mode 100644 index 00000000..e69de29b diff --git a/utilities/tests/resources/applications/myapp/deploy/templates/mytemplate.yaml b/utilities/tests/resources/applications/myapp/deploy/templates/mytemplate.yaml new file mode 100644 index 00000000..e69de29b diff --git a/utilities/tests/resources/applications/myapp/deploy/values.yaml b/utilities/tests/resources/applications/myapp/deploy/values.yaml new file mode 100644 index 00000000..2aaee442 --- /dev/null +++ b/utilities/tests/resources/applications/myapp/deploy/values.yaml @@ -0,0 +1,7 @@ +harness: + name: "I'm useless" + subdomain: mysubdomain + dependencies: + soft: + - legacy +a: b diff --git a/utilities/tests/resources/deployment-configuration/value-template.yaml b/utilities/tests/resources/deployment-configuration/value-template.yaml new file mode 100644 index 00000000..45a27d06 --- /dev/null +++ b/utilities/tests/resources/deployment-configuration/value-template.yaml @@ -0,0 +1 @@ +common: True \ No newline at end of file diff --git a/utilities/tests/resources/deployment-configuration/values-template-dev.yaml b/utilities/tests/resources/deployment-configuration/values-template-dev.yaml new file mode 100644 index 00000000..44673bfe --- /dev/null +++ b/utilities/tests/resources/deployment-configuration/values-template-dev.yaml @@ -0,0 +1,3 @@ +a: dev +database: + auto: false \ No newline at end of file diff --git a/utilities/tests/resources/deployment-configuration/values-template.yaml b/utilities/tests/resources/deployment-configuration/values-template.yaml new file mode 100644 index 00000000..b6888f2f --- /dev/null +++ b/utilities/tests/resources/deployment-configuration/values-template.yaml @@ -0,0 +1,5 @@ +mainapp: myapp +domain: myapp.local +a: b +database: + auto: true \ No newline at end of file diff --git a/utilities/tests/test_helm.py b/utilities/tests/test_helm.py new file mode 100644 index 00000000..df3d94ae --- /dev/null +++ b/utilities/tests/test_helm.py @@ -0,0 +1,72 @@ +import shutil +import yaml + +from cloudharness_utilities.helm import * + +HERE = os.path.dirname(os.path.realpath(__file__)) +RESOURCES = os.path.join(HERE, 'resources') +OUT = './deployment' +CLOUDHARNESS_ROOT = os.path.dirname(os.path.dirname(HERE)) + + +def test_collect_helm_values(): + values = create_helm_chart([CLOUDHARNESS_ROOT, RESOURCES], output_path=OUT, include=['samples', 'myapp'], + exclude=['events'], domain="my.local", + namespace='test', env='dev', local=False, tag=1, registry='reg') + + # Auto values + assert values[KEY_APPS]['myapp'][KEY_HARNESS]['deployment']['image'] == 'reg/myapp:1' + assert values[KEY_APPS]['myapp'][KEY_HARNESS]['name'] == 'myapp' + assert values[KEY_APPS]['legacy'][KEY_HARNESS]['name'] == 'legacy' + assert values[KEY_APPS]['accounts'][KEY_HARNESS]['deployment']['image'] == 'reg/accounts:1' + + # First level include apps + assert 'samples' in values[KEY_APPS] + assert 'myapp' in values[KEY_APPS] + + # Not included + assert 'jupyterhub' not in values[KEY_APPS] + + # Dependency include first level + assert 'accounts' in values[KEY_APPS] + assert 'legacy' in values[KEY_APPS] + + # Dependency include second level + assert 'argo' in values[KEY_APPS] + + # Explicit exclude overrides include + assert 'events' not in values[KEY_APPS] + + # Base values kept + assert values[KEY_APPS]['accounts'][KEY_HARNESS]['subdomain'] == 'accounts' + + # Defaults + assert 'service' in values[KEY_APPS]['legacy'][KEY_HARNESS] + assert 'common' in values[KEY_APPS]['legacy'] + assert 'common' in values[KEY_APPS]['accounts'] + # Values overriding + assert values[KEY_APPS]['accounts'][KEY_HARNESS]['deployment']['port'] == 'overridden' + + # Environment specific overriding + assert values[KEY_APPS]['accounts']['a'] == 'dev' + assert values['a'] == 'dev' + assert values['database']['auto'] == False + + # legacy reading + assert values[KEY_APPS]['accounts'][KEY_HARNESS]['deployment']['auto'] == 'overridden' + assert values[KEY_APPS]['legacy'][KEY_HARNESS]['deployment']['auto'] == 'legacy' + + helm_path = os.path.join(OUT, HELM_CHART_PATH) + + def exists(*args): + return os.path.exists(os.path.join(*args)) + + # Check files + assert exists(helm_path) + assert exists(helm_path, 'values.yaml') + assert exists(helm_path, 'resources/accounts/realm.json') + assert exists(helm_path, 'resources/accounts/aresource.txt') + assert exists(helm_path, 'resources/myapp/aresource.txt') + assert exists(helm_path, 'templates/myapp/mytemplate.yaml') + + shutil.rmtree(OUT) diff --git a/utilities/tests/test_utils.py b/utilities/tests/test_utils.py index f9914d9c..d831eace 100644 --- a/utilities/tests/test_utils.py +++ b/utilities/tests/test_utils.py @@ -5,12 +5,13 @@ HERE = os.path.dirname(os.path.realpath(__file__)).replace(os.path.sep, '/') + def test_image_name_from_docker_path(): assert app_name_from_path("a") == 'a' assert app_name_from_path("a/b") == 'a-b' assert app_name_from_path("a/src/b") == 'a-b' assert app_name_from_path("a/tasks/b") == 'a-b' - assert app_name_from_path("cloudharness/a/b") == 'a-b' + assert app_name_from_path("cloudharness/a/b") == 'cloudharness-a-b' def test_merge_configuration_directories(): @@ -26,7 +27,6 @@ def test_merge_configuration_directories(): assert os.path.exists(os.path.join(res_path, "b.yaml")) assert os.path.exists(os.path.join(res_path, "c.yaml")) - assert os.path.exists(os.path.join(res_path, "sub", "a.yaml")) assert os.path.exists(os.path.join(res_path, "sub", "b.yaml")) assert os.path.exists(os.path.join(res_path, "sub", "c.yaml")) @@ -38,7 +38,6 @@ def test_merge_configuration_directories(): assert a['b']['bb'] == 'bb' assert a['b']['bc'] == 'bc' - with open(os.path.join(res_path, "sub", "a.yaml")) as f: a = yaml.safe_load(f) assert a['a'] == 'a1' diff --git a/utilities/tox.ini b/utilities/tox.ini new file mode 100644 index 00000000..f517c410 --- /dev/null +++ b/utilities/tox.ini @@ -0,0 +1,9 @@ +[tox] +envlist = py3 + +[testenv] +deps=-r{toxinidir}/test-requirements.txt + +commands= + coverage run --source cloudharness_utilities -m pytest -v + coverage report -m \ No newline at end of file