diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 457d2c1451..6ace2303d9 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -6,6 +6,8 @@ labels: bug assignees: '' --- +**Checklist** +- [ ] I have searched budibase discussions and github issues to check if my issue already exists **Hosting** diff --git a/.github/workflows/release-develop.yml b/.github/workflows/release-develop.yml index 7ec18c0974..1ac6b20003 100644 --- a/.github/workflows/release-develop.yml +++ b/.github/workflows/release-develop.yml @@ -26,7 +26,7 @@ env: FEATURE_PREVIEW_URL: https://budirelease.live jobs: - release: + release-images: runs-on: ubuntu-latest steps: @@ -44,19 +44,12 @@ jobs: run: yarn install:pro develop - run: yarn - - run: yarn bootstrap + - run: yarn bootstrap - run: yarn lint - run: yarn build - run: yarn build:sdk - run: yarn test - - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@v1 - with: - aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - aws-region: eu-west-1 - - name: Publish budibase packages to NPM env: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} @@ -152,3 +145,54 @@ jobs: webhook-url: ${{ secrets.PROD_DEPLOY_WEBHOOK_URL }} content: "Release Env Deployment Complete: ${{ env.RELEASE_VERSION }} deployed to Budibase Release Env." embed-title: ${{ env.RELEASE_VERSION }} + + release-helm-chart: + needs: [release-images] + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Setup Helm + uses: azure/setup-helm@v1 + id: helm-install + + # due to helm repo index issue: https://github.com/helm/helm/issues/7363 + # we need to create new package in a different dir, merge the index and move the package back + - name: Build and release helm chart + run: | + git config user.name "Budibase Helm Bot" + git config user.email "<>" + git reset --hard + git pull + mkdir sync + echo "Packaging chart to sync dir" + helm package charts/budibase --version 0.0.0-develop --app-version develop --destination sync + echo "Packaging successful" + git checkout gh-pages + echo "Indexing helm repo" + helm repo index --merge docs/index.yaml sync + mv -f sync/* docs + rm -rf sync + echo "Pushing new helm release" + git add -A + git commit -m "Helm Release: develop" + git push + + trigger-deploy-to-qa-env: + needs: [release-helm-chart] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Get the current budibase release version + id: version + run: | + release_version=$(cat lerna.json | jq -r '.version') + echo "RELEASE_VERSION=$release_version" >> $GITHUB_ENV + + - uses: passeidireto/trigger-external-workflow-action@main + env: + PAYLOAD_VERSION: ${{ env.RELEASE_VERSION }} + with: + repository: budibase/budibase-deploys + event: deploy-budibase-develop-to-qa + github_pat: ${{ secrets.GH_ACCESS_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/release-selfhost.yml b/.github/workflows/release-selfhost.yml index d78180fdc7..12fb8f5a9d 100644 --- a/.github/workflows/release-selfhost.yml +++ b/.github/workflows/release-selfhost.yml @@ -67,16 +67,24 @@ jobs: uses: azure/setup-helm@v1 id: helm-install + # due to helm repo index issue: https://github.com/helm/helm/issues/7363 + # we need to create new package in a different dir, merge the index and move the package back - name: Build and release helm chart run: | git config user.name "Budibase Helm Bot" git config user.email "<>" git reset --hard git pull - helm package charts/budibase + mkdir sync + echo "Packaging chart to sync dir" + helm package charts/budibase --version "$RELEASE_VERSION" --app-version "$RELEASE_VERSION" --destination sync + echo "Packaging successful" git checkout gh-pages - mv *.tgz docs - helm repo index docs + echo "Indexing helm repo" + helm repo index --merge docs/index.yaml sync + mv -f sync/* docs + rm -rf sync + echo "Pushing new helm release" git add -A git commit -m "Helm Release: ${{ env.RELEASE_VERSION }}" git push diff --git a/.github/workflows/smoke_test.yaml b/.github/workflows/smoke_test.yaml index cffb914aaf..29c7f5f85a 100644 --- a/.github/workflows/smoke_test.yaml +++ b/.github/workflows/smoke_test.yaml @@ -18,30 +18,18 @@ jobs: - run: yarn - run: yarn bootstrap - run: yarn build - - name: Pull cypress.env.yaml from budibase-infra + - name: Pull from budibase-infra run: | curl -H "Authorization: token ${{ secrets.GH_PERSONAL_TOKEN }}" \ -H 'Accept: application/vnd.github.v3.raw' \ - -o packages/builder/cypress.env.json \ - -L https://api.github.com/repos/budibase/budibase-infra/contents/test/cypress.env.json - wc -l packages/builder/cypress.env.json - - - name: Cypress run - id: cypress - continue-on-error: true - uses: cypress-io/github-action@v2 - with: - record: true - install: false - tag: nightly - command: yarn test:e2e:ci:record - env: - CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} + -o + -L + wc -l - uses: actions/upload-artifact@v3 with: name: Test Reports - path: packages/builder/cypress/reports/testReport.html + path: # TODO: enable once running in QA test env # - name: Configure AWS Credentials @@ -54,11 +42,3 @@ jobs: # - name: Upload test results HTML # uses: aws-actions/configure-aws-credentials@v1 # run: aws s3 cp packages/builder/cypress/reports/testReport.html s3://{{ secrets.BUDI_QA_REPORTS_BUCKET_NAME }}/$GITHUB_RUN_ID/index.html - - - name: Cypress Discord Notify - run: yarn test:e2e:ci:notify - env: - CYPRESS_WEBHOOK_URL: ${{ secrets.BUDI_QA_WEBHOOK }} - CYPRESS_OUTCOME: ${{ steps.cypress.outcome }} - CYPRESS_DASHBOARD_URL: ${{ steps.cypress.outputs.dashboardUrl }} - GITHUB_RUN_URL: $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID diff --git a/.gitignore b/.gitignore index 6eb9eed952..b3dc8af0d4 100644 --- a/.gitignore +++ b/.gitignore @@ -107,3 +107,5 @@ stats.html # plugins budibase-component budibase-datasource + +*.iml diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000000..e0bcfe01fb --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +v14.19.3 diff --git a/.python-version b/.python-version new file mode 100644 index 0000000000..371cfe355d --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.11.1 diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 0000000000..8a1af3c071 --- /dev/null +++ b/.tool-versions @@ -0,0 +1,2 @@ +nodejs 14.19.3 +python 3.11.1 \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000000..03d0aa4411 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,6 @@ +{ + "recommendations": [ + "esbenp.prettier-vscode", + "svelte.svelte-vscode" + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 4838a4fd89..ece537efac 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,19 +1,28 @@ { - "editor.formatOnSave": true, - "editor.codeActionsOnSave": { - "source.fixAll": true - }, - "editor.defaultFormatter": "svelte.svelte-vscode", - "[json]": { - "editor.defaultFormatter": "vscode.json-language-features" - }, - "[javascript]": { - "editor.defaultFormatter": "esbenp.prettier-vscode" - }, - "debug.javascript.terminalOptions": { - "skipFiles": [ - "${workspaceFolder}/packages/backend-core/node_modules/**", - "/**" - ] - }, + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll": true + }, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "[json]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[javascript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "debug.javascript.terminalOptions": { + "skipFiles": [ + "${workspaceFolder}/packages/backend-core/node_modules/**", + "/**" + ] + }, + "[typescript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[dockercompose]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[svelte]": { + "editor.defaultFormatter": "svelte.svelte-vscode" + } } diff --git a/charts/budibase/Chart.yaml b/charts/budibase/Chart.yaml index 85d4165252..05b3f24dbd 100644 --- a/charts/budibase/Chart.yaml +++ b/charts/budibase/Chart.yaml @@ -11,8 +11,10 @@ sources: - https://github.com/Budibase/budibase - https://budibase.com type: application -version: 0.2.11 -appVersion: 1.0.214 +# populates on packaging +version: 0.0.0 +# populates on packaging +appVersion: 0.0.0 dependencies: - name: couchdb version: 3.3.4 diff --git a/charts/budibase/templates/app-service-deployment.yaml b/charts/budibase/templates/app-service-deployment.yaml index a3e4790430..9ac8a1e7c6 100644 --- a/charts/budibase/templates/app-service-deployment.yaml +++ b/charts/budibase/templates/app-service-deployment.yaml @@ -4,9 +4,6 @@ metadata: annotations: kompose.cmd: kompose convert kompose.version: 1.21.0 (992df58d8) -{{ if .Values.globals.logAnnotations }} -{{ toYaml .Values.globals.logAnnotations | indent 4 }} -{{ end }} creationTimestamp: null labels: io.kompose.service: app-service @@ -23,6 +20,9 @@ spec: annotations: kompose.cmd: kompose convert kompose.version: 1.21.0 (992df58d8) +{{ if .Values.services.apps.annotations }} +{{- toYaml .Values.services.apps.annotations | indent 8 -}} +{{ end }} creationTimestamp: null labels: io.kompose.service: app-service @@ -67,6 +67,8 @@ spec: - name: AWS_REGION value: {{ .Values.services.objectStore.region }} {{ end }} + - name: MINIO_ENABLED + value: {{ .Values.services.objectStore.minio | quote }} - name: MINIO_ACCESS_KEY valueFrom: secretKeyRef: @@ -77,13 +79,19 @@ spec: secretKeyRef: name: {{ template "budibase.fullname" . }} key: objectStoreSecret + - name: CLOUDFRONT_CDN + value: {{ .Values.services.objectStore.cloudfront.cdn | quote }} + - name: CLOUDFRONT_PUBLIC_KEY_ID + value: {{ .Values.services.objectStore.cloudfront.publicKeyId | quote }} + - name: CLOUDFRONT_PRIVATE_KEY_64 + value: {{ .Values.services.objectStore.cloudfront.privateKey64 | quote }} - name: MINIO_URL value: {{ .Values.services.objectStore.url }} - name: PLUGIN_BUCKET_NAME value: {{ .Values.services.objectStore.pluginBucketName | quote }} - name: APPS_BUCKET_NAME value: {{ .Values.services.objectStore.appsBucketName | quote }} - - name: GLOBAL_CLOUD_BUCKET_NAME + - name: GLOBAL_BUCKET_NAME value: {{ .Values.services.objectStore.globalBucketName | quote }} - name: BACKUPS_BUCKET_NAME value: {{ .Values.services.objectStore.backupsBucketName | quote }} @@ -131,6 +139,8 @@ spec: value: {{ .Values.globals.automationMaxIterations | quote }} - name: TENANT_FEATURE_FLAGS value: {{ .Values.globals.tenantFeatureFlags | quote }} + - name: ENCRYPTION_KEY + value: {{ .Values.globals.bbEncryptionKey | quote }} {{ if .Values.globals.bbAdminUserEmail }} - name: BB_ADMIN_USER_EMAIL value: {{ .Values.globals.bbAdminUserEmail | quote }} diff --git a/charts/budibase/templates/proxy-service-deployment.yaml b/charts/budibase/templates/proxy-service-deployment.yaml index 00c12271db..6064905c4c 100644 --- a/charts/budibase/templates/proxy-service-deployment.yaml +++ b/charts/budibase/templates/proxy-service-deployment.yaml @@ -4,9 +4,6 @@ metadata: annotations: kompose.cmd: kompose convert kompose.version: 1.21.0 (992df58d8) -{{ if .Values.globals.logAnnotations }} -{{ toYaml .Values.globals.logAnnotations | indent 4 }} -{{ end }} creationTimestamp: null labels: app.kubernetes.io/name: budibase-proxy @@ -23,6 +20,9 @@ spec: annotations: kompose.cmd: kompose convert kompose.version: 1.21.0 (992df58d8) +{{ if .Values.services.proxy.annotations }} +{{- toYaml .Values.services.proxy.annotations | indent 8 -}} +{{ end }} creationTimestamp: null labels: app.kubernetes.io/name: budibase-proxy diff --git a/charts/budibase/templates/worker-service-deployment.yaml b/charts/budibase/templates/worker-service-deployment.yaml index 44bbb8aa20..a16f839ea7 100644 --- a/charts/budibase/templates/worker-service-deployment.yaml +++ b/charts/budibase/templates/worker-service-deployment.yaml @@ -4,9 +4,6 @@ metadata: annotations: kompose.cmd: kompose convert kompose.version: 1.21.0 (992df58d8) -{{ if .Values.globals.logAnnotations }} -{{ toYaml .Values.globals.logAnnotations | indent 4 }} -{{ end }} creationTimestamp: null labels: io.kompose.service: worker-service @@ -24,6 +21,9 @@ spec: annotations: kompose.cmd: kompose convert kompose.version: 1.21.0 (992df58d8) +{{ if .Values.services.worker.annotations }} +{{- toYaml .Values.services.worker.annotations | indent 8 -}} +{{ end }} creationTimestamp: null labels: io.kompose.service: worker-service @@ -68,6 +68,8 @@ spec: - name: AWS_REGION value: {{ .Values.services.objectStore.region }} {{ end }} + - name: MINIO_ENABLED + value: {{ .Values.services.objectStore.minio | quote }} - name: MINIO_ACCESS_KEY valueFrom: secretKeyRef: @@ -80,11 +82,17 @@ spec: key: objectStoreSecret - name: MINIO_URL value: {{ .Values.services.objectStore.url }} + - name: CLOUDFRONT_CDN + value: {{ .Values.services.objectStore.cloudfront.cdn | quote }} + - name: CLOUDFRONT_PUBLIC_KEY_ID + value: {{ .Values.services.objectStore.cloudfront.publicKeyId | quote }} + - name: CLOUDFRONT_PRIVATE_KEY_64 + value: {{ .Values.services.objectStore.cloudfront.privateKey64 | quote }} - name: PLUGIN_BUCKET_NAME value: {{ .Values.services.objectStore.pluginBucketName | quote }} - name: APPS_BUCKET_NAME value: {{ .Values.services.objectStore.appsBucketName | quote }} - - name: GLOBAL_CLOUD_BUCKET_NAME + - name: GLOBAL_BUCKET_NAME value: {{ .Values.services.objectStore.globalBucketName | quote }} - name: BACKUPS_BUCKET_NAME value: {{ .Values.services.objectStore.backupsBucketName | quote }} @@ -138,6 +146,8 @@ spec: value: {{ .Values.globals.google.secret | quote }} - name: TENANT_FEATURE_FLAGS value: {{ .Values.globals.tenantFeatureFlags | quote }} + - name: ENCRYPTION_KEY + value: {{ .Values.globals.bbEncryptionKey | quote }} {{ if .Values.globals.elasticApmEnabled }} - name: ELASTIC_APM_ENABLED value: {{ .Values.globals.elasticApmEnabled | quote }} diff --git a/charts/budibase/values.yaml b/charts/budibase/values.yaml index 5c20fc220a..dd75b2daa3 100644 --- a/charts/budibase/values.yaml +++ b/charts/budibase/values.yaml @@ -22,12 +22,6 @@ serviceAccount: podAnnotations: {} -# logAnnotations: -# co.elastic.logs/multiline.type: pattern -# co.elastic.logs/multiline.pattern: '^[[:space:]]' -# co.elastic.logs/multiline.negate: false -# co.elastic.logs/multiline.match: after - podSecurityContext: {} # fsGroup: 2000 @@ -82,7 +76,7 @@ affinity: {} globals: appVersion: "latest" budibaseEnv: PRODUCTION - tenantFeatureFlags: "*:LICENSING,*:USER_GROUPS" + tenantFeatureFlags: "*:LICENSING,*:USER_GROUPS,*:ONBOARDING_TOUR" enableAnalytics: "1" sentryDSN: "" posthogToken: "phc_bIjZL7oh2GEUd2vqvTBH8WvrX0fWTFQMs6H5KQxiUxU" @@ -130,6 +124,10 @@ services: minio: 'http://minio-service.{{ .Release.Namespace }}.svc.{{ .Values.services.dns }}:{{ .Values.services.objectStore.port }}' couchdb: 'http://{{ .Release.Name }}-svc-couchdb:{{ .Values.services.couchdb.port }}' resources: {} +# annotations: +# co.elastic.logs/module: nginx +# co.elastic.logs/fileset.stdout: access +# co.elastic.logs/fileset.stderr: error apps: port: 4002 @@ -137,11 +135,20 @@ services: logLevel: info resources: {} # nodeDebug: "" # set the value of NODE_DEBUG - +# annotations: +# co.elastic.logs/multiline.type: pattern +# co.elastic.logs/multiline.pattern: '^[[:space:]]' +# co.elastic.logs/multiline.negate: false +# co.elastic.logs/multiline.match: after worker: port: 4003 replicaCount: 1 resources: {} +# annotations: +# co.elastic.logs/multiline.type: pattern +# co.elastic.logs/multiline.pattern: '^[[:space:]]' +# co.elastic.logs/multiline.negate: false +# co.elastic.logs/multiline.match: after couchdb: enabled: true @@ -172,6 +179,7 @@ services: resources: {} objectStore: + # Set to false if using another object store such as S3 minio: true browser: true port: 9000 @@ -187,6 +195,13 @@ services: ## set, choosing the default provisioner. storageClass: "" resources: {} + cloudfront: + # Set the url of a distribution to enable cloudfront + cdn: "" + # ID of public key stored in cloudfront + publicKeyId: "" + # Base64 encoded private key for the above public key + privateKey64: "" # Override values in couchDB subchart couchdb: diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index fb0848596c..6e667d23a8 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -9,7 +9,6 @@ From opening a bug report to creating a pull request: every contribution is appr - [Glossary of Terms](#glossary-of-terms) - [Contributing to Budibase](#contributing-to-budibase) - ## Not Sure Where to Start? Budibase is a low-code web application builder that creates svelte-based web applications. @@ -22,7 +21,7 @@ Budibase is a monorepo managed by [lerna](https://github.com/lerna/lerna). Lerna - **packages/server** - The budibase server. This [Koa](https://koajs.com/) app is responsible for serving the JS for the builder and budibase apps, as well as providing the API for interaction with the database and file system. -- **packages/worker** - This [Koa](https://koajs.com/) app is responsible for providing global apis for managing your budibase installation. Authentication, Users, Email, Org and Auth configs are all provided by the worker. +- **packages/worker** - This [Koa](https://koajs.com/) app is responsible for providing global apis for managing your budibase installation. Authentication, Users, Email, Org and Auth configs are all provided by the worker. ## Contributor License Agreement (CLA) @@ -45,7 +44,7 @@ A client represents a single budibase customer. Each budibase client will have 1 ### App -A client can have one or more budibase applications. Budibase applications would be things like "Developer Inventory Management" or "Goat Herder CRM". Think of a budibase application as a tree. +A client can have one or more budibase applications. Budibase applications would be things like "Developer Inventory Management" or "Goat Herder CRM". Think of a budibase application as a tree. ### Database @@ -73,28 +72,55 @@ A component is the basic frontend building block of a budibase app. ### Component Library -Component libraries are collections of components as well as the definition of their props contained in a file called `components.json`. +Component libraries are collections of components as well as the definition of their props contained in a file called `components.json`. ## Contributing to Budibase -* Please maintain the existing code style. +- Please maintain the existing code style. -* Please try to keep your commits small and focused. +- Please try to keep your commits small and focused. -* Please write tests. +- Please write tests. -* If the project diverges from your branch, please rebase instead of merging. This makes the commit graph easier to read. +- If the project diverges from your branch, please rebase instead of merging. This makes the commit graph easier to read. -* Once your work is completed, please raise a PR against the `develop` branch with some information about what has changed and why. +- Once your work is completed, please raise a PR against the `develop` branch with some information about what has changed and why. ### Getting Started For Contributors -#### 1. Prerequisites -NodeJS Version `14.x.x` +#### 1. Prerequisites -*yarn -* `npm install -g yarn` +- NodeJS version `14.x.x` +- Python version `3.x` -*jest* - `npm install -g jest` +### Using asdf (recommended) + +Asdf is a package manager that allows managing multiple dependencies. + +You can install them following any of the steps described below: + +- Install using script (only for mac users): + +`./scripts/install-contributor-dependencies.sh` + +- Or, manually: + + - Installation steps: https://asdf-vm.com/guide/getting-started.html + - asdf plugin add nodejs + - asdf plugin add python + - npm install -g yarn + +### Using NVM and pyenv + +- NVM: + - Install: https://github.com/nvm-sh/nvm#installing-and-updating + - Setup: `nvm use` +- Pyenv: + + - Install: https://github.com/pyenv/pyenv#installation + - Setup: `pyenv install -v 3.7.2` + +- _yarn -_ `npm install -g yarn` #### 2. Clone this repository @@ -102,7 +128,7 @@ NodeJS Version `14.x.x` then `cd ` into your local copy. -#### 3. Install and Build +#### 3. Install and Build | **NOTE**: On Windows, all yarn commands must be executed on a bash shell (e.g. git bash) @@ -134,9 +160,9 @@ This will enable watch mode for both the builder app, server, client library and #### 5. Debugging using VS Code -To debug the budibase server and worker a VS Code launch configuration has been provided. +To debug the budibase server and worker a VS Code launch configuration has been provided. -Visit the debug window and select `Budibase Server` or `Budibase Worker` to debug the respective component. +Visit the debug window and select `Budibase Server` or `Budibase Worker` to debug the respective component. Alternatively to start both components simultaneously select `Start Budibase`. In addition to the above, the remaining budibase components may be run in dev mode using: `yarn dev:noserver`. @@ -156,11 +182,11 @@ For the backend we run [Redis](https://redis.io/), [CouchDB](https://couchdb.apa When you are running locally, budibase stores data on disk using docker volumes. The volumes and the types of data associated with each are: -- `redis_data` +- `redis_data` - Sessions, email tokens -- `couchdb3_data` +- `couchdb3_data` - Global and app databases -- `minio_data` +- `minio_data` - App manifest, budibase client, static assets ### Development Modes @@ -172,34 +198,42 @@ A combination of environment variables controls the mode budibase runs in. Yarn commands can be used to mimic the different modes as described in the sections below: #### Self Hosted -The default mode. A single tenant installation with no usage restrictions. + +The default mode. A single tenant installation with no usage restrictions. To enable this mode, use: + ``` yarn mode:self ``` #### Cloud -The cloud mode, with account portal turned off. + +The cloud mode, with account portal turned off. To enable this mode, use: + ``` yarn mode:cloud ``` -#### Cloud & Account -The cloud mode, with account portal turned on. This is a replica of the mode that runs at https://budibase.app +#### Cloud & Account + +The cloud mode, with account portal turned on. This is a replica of the mode that runs at https://budibase.app To enable this mode, use: + ``` yarn mode:account ``` + ### CI - An overview of the CI pipelines can be found [here](../.github/workflows/README.md) + +An overview of the CI pipelines can be found [here](../.github/workflows/README.md) ### Pro -@budibase/pro is the closed source package that supports licensed features in budibase. By default the package will be pulled from NPM and will not normally need to be touched in local development. If you require to update code inside the pro package it can be cloned to the same root level as budibase, e.g. +@budibase/pro is the closed source package that supports licensed features in budibase. By default the package will be pulled from NPM and will not normally need to be touched in local development. If you require to update code inside the pro package it can be cloned to the same root level as budibase, e.g. ``` . @@ -207,13 +241,14 @@ yarn mode:account |_ budibase-pro ``` -Note that only budibase maintainers will be able to access the pro repo. +Note that only budibase maintainers will be able to access the pro repo. -The `yarn bootstrap` command can be used to replace the NPM supplied dependency with the local source aware version. This is achieved using the `yarn link` command. To see specifically how dependencies are linked see [scripts/link-dependencies.sh](../scripts/link-dependencies.sh). The same link script is used to link dependencies to account-portal in local dev. +The `yarn bootstrap` command can be used to replace the NPM supplied dependency with the local source aware version. This is achieved using the `yarn link` command. To see specifically how dependencies are linked see [scripts/link-dependencies.sh](../scripts/link-dependencies.sh). The same link script is used to link dependencies to account-portal in local dev. ### Troubleshooting Sometimes, things go wrong. This can be due to incompatible updates on the budibase platform. To clear down your development environment and start again follow **Step 6. Cleanup**, then proceed from **Step 3. Install and Build** in the setup guide above to create a fresh Budibase installation. + ### Running tests #### End-to-end Tests @@ -226,12 +261,11 @@ yarn test:e2e Or if you are in the builder you can run `yarn cy:test`. - ### Other Useful Information -* The contributors are listed in [AUTHORS.md](https://github.com/Budibase/budibase/blob/master/.github/AUTHORS.md) (add yourself). +- The contributors are listed in [AUTHORS.md](https://github.com/Budibase/budibase/blob/master/.github/AUTHORS.md) (add yourself). -* This project uses a modified version of the MPLv2 license, see [LICENSE](https://github.com/budibase/server/blob/master/LICENSE). +- This project uses a modified version of the MPLv2 license, see [LICENSE](https://github.com/budibase/server/blob/master/LICENSE). -* We use the [C4 (Collective Code Construction Contract)](https://rfc.zeromq.org/spec:42/C4/) process for contributions. +- We use the [C4 (Collective Code Construction Contract)](https://rfc.zeromq.org/spec:42/C4/) process for contributions. Please read this if you are unfamiliar with it. diff --git a/examples/nextjs-api-sales/yarn.lock b/examples/nextjs-api-sales/yarn.lock index f47fb84e33..1f34ca2ee2 100644 --- a/examples/nextjs-api-sales/yarn.lock +++ b/examples/nextjs-api-sales/yarn.lock @@ -2,27 +2,6 @@ # yarn lockfile v1 -"@babel/code-frame@^7.0.0": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" - integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== - dependencies: - "@babel/highlight" "^7.16.7" - -"@babel/helper-validator-identifier@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" - integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== - -"@babel/highlight@^7.16.7": - version "7.16.10" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88" - integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw== - dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - chalk "^2.0.0" - js-tokens "^4.0.0" - "@babel/runtime-corejs3@^7.10.2": version "7.17.2" resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.17.2.tgz#fdca2cd05fba63388babe85d349b6801b008fd13" @@ -53,11 +32,6 @@ minimatch "^3.0.4" strip-json-comments "^3.1.1" -"@gar/promisify@^1.0.1": - version "1.1.3" - resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" - integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== - "@humanwhocodes/config-array@^0.9.2": version "0.9.5" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.9.5.tgz#2cbaf9a89460da24b5ca6531b8bbfc23e1df50c7" @@ -160,52 +134,21 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@npmcli/fs@^1.0.0": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-1.1.1.tgz#72f719fe935e687c56a4faecf3c03d06ba593257" - integrity sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ== - dependencies: - "@gar/promisify" "^1.0.1" - semver "^7.3.5" - -"@npmcli/move-file@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.1.2.tgz#1a82c3e372f7cae9253eb66d72543d6b8685c674" - integrity sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg== - dependencies: - mkdirp "^1.0.4" - rimraf "^3.0.2" - "@rushstack/eslint-patch@^1.0.8": version "1.1.0" resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.1.0.tgz#7f698254aadf921e48dda8c0a6b304026b8a9323" integrity sha512-JLo+Y592QzIE+q7Dl2pMUtt4q8SKYI5jDrZxrozEQxnGVOyYE+GWK9eLkwTaeN9DDctlaRAQ3TBmzZ1qdLE30A== -"@tootallnate/once@1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" - integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== - "@types/json5@^0.0.29": version "0.0.29" resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= -"@types/minimist@^1.2.0": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c" - integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ== - "@types/node@17.0.21": version "17.0.21" resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.21.tgz#864b987c0c68d07b4345845c3e63b75edd143644" integrity sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ== -"@types/normalize-package-data@^2.4.0": - version "2.4.1" - resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301" - integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw== - "@types/prop-types@*": version "15.7.4" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11" @@ -269,11 +212,6 @@ "@typescript-eslint/types" "5.14.0" eslint-visitor-keys "^3.0.0" -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== - acorn-jsx@^5.3.1: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" @@ -284,31 +222,7 @@ acorn@^8.7.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== -agent-base@6, agent-base@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" - integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== - dependencies: - debug "4" - -agentkeepalive@^4.1.3: - version "4.2.1" - resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.2.1.tgz#a7975cbb9f83b367f06c90cc51ff28fe7d499717" - integrity sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA== - dependencies: - debug "^4.1.0" - depd "^1.1.2" - humanize-ms "^1.2.1" - -aggregate-error@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" - integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== - dependencies: - clean-stack "^2.0.0" - indent-string "^4.0.0" - -ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4: +ajv@^6.10.0, ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -323,40 +237,20 @@ ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: +ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: color-convert "^2.0.1" -"aproba@^1.0.3 || ^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" - integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== - -are-we-there-yet@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz#372e0e7bd279d8e94c653aaa1f67200884bf3e1c" - integrity sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw== +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== dependencies: - delegates "^1.0.0" - readable-stream "^3.6.0" - -are-we-there-yet@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-3.0.0.tgz#ba20bd6b553e31d62fc8c31bd23d22b95734390d" - integrity sha512-0GWpv50YSOcLXaN6/FAKY3vfRbllXWV2xvfA/oKJF8pzFhWXPV+yjhJXDBbjscDYowv7Yw1A3uigpzn5iEGTyw== - dependencies: - delegates "^1.0.0" - readable-stream "^3.6.0" + normalize-path "^3.0.0" + picomatch "^2.0.4" argparse@^2.0.1: version "2.0.1" @@ -405,48 +299,11 @@ array.prototype.flatmap@^1.2.5: define-properties "^1.1.3" es-abstract "^1.19.0" -arrify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= - -asn1@~0.2.3: - version "0.2.6" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" - integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== - dependencies: - safer-buffer "~2.1.0" - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= - ast-types-flow@^0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= -async-foreach@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542" - integrity sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI= - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= - -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= - -aws4@^1.8.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" - integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== - axe-core@^4.3.5: version "4.4.1" resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.4.1.tgz#7dbdc25989298f9ad006645cd396782443757413" @@ -462,12 +319,10 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -bcrypt-pbkdf@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= - dependencies: - tweetnacl "^0.14.3" +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== brace-expansion@^1.1.7: version "1.1.11" @@ -477,7 +332,7 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^3.0.1: +braces@^3.0.1, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -489,30 +344,6 @@ bulma@^0.9.3: resolved "https://registry.yarnpkg.com/bulma/-/bulma-0.9.3.tgz#ddccb7436ebe3e21bf47afe01d3c43a296b70243" integrity sha512-0d7GNW1PY4ud8TWxdNcP6Cc8Bu7MxcntD/RRLGWuiw/s0a9P+XlH/6QoOIrmbj6o8WWJzJYhytiu9nFjTszk1g== -cacache@^15.2.0: - version "15.3.0" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.3.0.tgz#dc85380fb2f556fe3dda4c719bfa0ec875a7f1eb" - integrity sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ== - dependencies: - "@npmcli/fs" "^1.0.0" - "@npmcli/move-file" "^1.0.1" - chownr "^2.0.0" - fs-minipass "^2.0.0" - glob "^7.1.4" - infer-owner "^1.0.4" - lru-cache "^6.0.0" - minipass "^3.1.1" - minipass-collect "^1.0.2" - minipass-flush "^1.0.5" - minipass-pipeline "^1.2.2" - mkdirp "^1.0.3" - p-map "^4.0.0" - promise-inflight "^1.0.1" - rimraf "^3.0.2" - ssri "^8.0.1" - tar "^6.0.2" - unique-filename "^1.1.1" - call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" @@ -526,40 +357,12 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -camelcase-keys@^6.2.2: - version "6.2.2" - resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-6.2.2.tgz#5e755d6ba51aa223ec7d3d52f25778210f9dc3c0" - integrity sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg== - dependencies: - camelcase "^5.3.1" - map-obj "^4.0.0" - quick-lru "^4.0.1" - -camelcase@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - caniuse-lite@^1.0.30001283: version "1.0.30001314" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001314.tgz#65c7f9fb7e4594fca0a333bec1d8939662377596" integrity sha512-0zaSO+TnCHtHJIbpLroX7nsD+vYuOVjl3uzFbJO1wMVbuveJA0RK2WcQA9ZUIOiO0/ArMiMgHJLxfEZhQiC0kw== -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= - -chalk@^2.0.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^4.0.0, chalk@^4.1.2: +chalk@^4.0.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -567,31 +370,20 @@ chalk@^4.0.0, chalk@^4.1.2: ansi-styles "^4.1.0" supports-color "^7.1.0" -chownr@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" - integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== - -clean-stack@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" - integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== - -cliui@^7.0.2: - version "7.0.4" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" - integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== +"chokidar@>=3.0.0 <4.0.0": + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.0" - wrap-ansi "^7.0.0" - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" color-convert@^2.0.1: version "2.0.1" @@ -600,54 +392,22 @@ color-convert@^2.0.1: dependencies: color-name "~1.1.4" -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= - color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -color-support@^1.1.2, color-support@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" - integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== - -combined-stream@^1.0.6, combined-stream@~1.0.6: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -console-control-strings@^1.0.0, console-control-strings@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= - core-js-pure@^3.20.2: version "3.21.1" resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.21.1.tgz#8c4d1e78839f5f46208de7230cebfb72bc3bdb51" integrity sha512-12VZfFIu+wyVbBebyHmRTuEE/tZrB4tJToWcwAMcsp3h4+sHR+fMJWbKpYiCRWlhFBq+KNyO8rIV9rTkeVmznQ== -core-util-is@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= - -core-util-is@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" - integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== - -cross-spawn@^7.0.2, cross-spawn@^7.0.3: +cross-spawn@^7.0.2: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -666,25 +426,11 @@ damerau-levenshtein@^1.0.7: resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= - dependencies: - assert-plus "^1.0.0" - data-uri-to-buffer@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz#b5db46aea50f6176428ac05b73be39a57701a64b" integrity sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA== -debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2: - version "4.3.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" - integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== - dependencies: - ms "2.1.2" - debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -699,18 +445,12 @@ debug@^3.2.7: dependencies: ms "^2.1.1" -decamelize-keys@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" - integrity sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk= +debug@^4.1.1, debug@^4.3.1, debug@^4.3.2: + version "4.3.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" + integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== dependencies: - decamelize "^1.1.0" - map-obj "^1.0.0" - -decamelize@^1.1.0, decamelize@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + ms "2.1.2" deep-is@^0.1.3: version "0.1.4" @@ -724,21 +464,6 @@ define-properties@^1.1.3: dependencies: object-keys "^1.0.12" -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= - -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= - -depd@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= - dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -760,48 +485,11 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" -ecc-jsbn@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= - dependencies: - jsbn "~0.1.0" - safer-buffer "^2.1.0" - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - emoji-regex@^9.2.2: version "9.2.2" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== -encoding@^0.1.12: - version "0.1.13" - resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" - integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== - dependencies: - iconv-lite "^0.6.2" - -env-paths@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" - integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== - -err-code@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9" - integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA== - -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - es-abstract@^1.19.0, es-abstract@^1.19.1: version "1.19.1" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.19.1.tgz#d4885796876916959de78edaa0df456627115ec3" @@ -837,16 +525,6 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" @@ -1055,21 +733,6 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -extend@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= - -extsprintf@^1.2.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" - integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== - fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -1132,14 +795,6 @@ find-up@^2.1.0: dependencies: locate-path "^2.0.0" -find-up@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - flat-cache@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" @@ -1153,20 +808,6 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3" integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= - -form-data@~2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" - integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - formdata-polyfill@^4.0.10: version "4.0.10" resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" @@ -1174,18 +815,16 @@ formdata-polyfill@^4.0.10: dependencies: fetch-blob "^3.1.2" -fs-minipass@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" - integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== - dependencies: - minipass "^3.0.0" - fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" @@ -1196,48 +835,6 @@ functional-red-black-tree@^1.0.1: resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= -gauge@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-3.0.2.tgz#03bf4441c044383908bcfa0656ad91803259b395" - integrity sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q== - dependencies: - aproba "^1.0.3 || ^2.0.0" - color-support "^1.1.2" - console-control-strings "^1.0.0" - has-unicode "^2.0.1" - object-assign "^4.1.1" - signal-exit "^3.0.0" - string-width "^4.2.3" - strip-ansi "^6.0.1" - wide-align "^1.1.2" - -gauge@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-4.0.2.tgz#c3777652f542b6ef62797246e8c7caddecb32cc7" - integrity sha512-aSPRm2CvA9R8QyU5eXMFPd+cYkyxLsXHd2l5/FOH2V/eml//M04G6KZOmTap07O1PvEwNcl2NndyLfK8g3QrKA== - dependencies: - ansi-regex "^5.0.1" - aproba "^1.0.3 || ^2.0.0" - color-support "^1.1.3" - console-control-strings "^1.1.0" - has-unicode "^2.0.1" - signal-exit "^3.0.7" - string-width "^4.2.3" - strip-ansi "^6.0.1" - wide-align "^1.1.5" - -gaze@^1.0.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.3.tgz#c441733e13b927ac8c0ff0b4c3b033f28812924a" - integrity sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g== - dependencies: - globule "^1.0.0" - -get-caller-file@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" @@ -1247,11 +844,6 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: has "^1.0.3" has-symbols "^1.0.1" -get-stdin@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" - integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= - get-symbol-description@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" @@ -1260,14 +852,7 @@ get-symbol-description@^1.0.0: call-bind "^1.0.2" get-intrinsic "^1.1.1" -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= - dependencies: - assert-plus "^1.0.0" - -glob-parent@^5.1.2: +glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== @@ -1281,7 +866,7 @@ glob-parent@^6.0.1: dependencies: is-glob "^4.0.3" -glob@7.1.7, glob@~7.1.1: +glob@7.1.7: version "7.1.7" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== @@ -1293,7 +878,7 @@ glob@7.1.7, glob@~7.1.1: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.0, glob@^7.0.3, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.7: +glob@^7.1.3, glob@^7.1.7: version "7.2.0" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== @@ -1324,48 +909,11 @@ globby@^11.0.4: merge2 "^1.4.1" slash "^3.0.0" -globule@^1.0.0: - version "1.3.3" - resolved "https://registry.yarnpkg.com/globule/-/globule-1.3.3.tgz#811919eeac1ab7344e905f2e3be80a13447973c2" - integrity sha512-mb1aYtDbIjTu4ShMB85m3UzjX9BVKe9WCzsnfMSZk+K5GpIbBOexgg4PPCt5eHDEG5/ZQAUX2Kct02zfiPLsKg== - dependencies: - glob "~7.1.1" - lodash "~4.17.10" - minimatch "~3.0.2" - -graceful-fs@^4.2.6: - version "4.2.9" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" - integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== - -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= - -har-validator@~5.1.3: - version "5.1.5" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" - integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== - dependencies: - ajv "^6.12.3" - har-schema "^2.0.0" - -hard-rejection@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" - integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA== - has-bigints@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - has-flag@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" @@ -1383,11 +931,6 @@ has-tostringtag@^1.0.0: dependencies: has-symbols "^1.0.2" -has-unicode@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= - has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" @@ -1395,63 +938,6 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" -hosted-git-info@^2.1.4: - version "2.8.9" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" - integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== - -hosted-git-info@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz#827b82867e9ff1c8d0c4d9d53880397d2c86d224" - integrity sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA== - dependencies: - lru-cache "^6.0.0" - -http-cache-semantics@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" - integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== - -http-proxy-agent@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" - integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== - dependencies: - "@tootallnate/once" "1" - agent-base "6" - debug "4" - -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -https-proxy-agent@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" - integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== - dependencies: - agent-base "6" - debug "4" - -humanize-ms@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" - integrity sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0= - dependencies: - ms "^2.0.0" - -iconv-lite@^0.6.2: - version "0.6.3" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" - integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== - dependencies: - safer-buffer ">= 2.1.2 < 3.0.0" - ignore@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" @@ -1462,6 +948,11 @@ ignore@^5.2.0: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== +immutable@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.2.1.tgz#8a4025691018c560a40c67e43d698f816edc44d4" + integrity sha512-7WYV7Q5BTs0nlQm7tl92rDYYoyELLKHoDMBKhrxEoiV4mrfVdRz8hzPiYOzH7yWjzoVEamxRuAqhxL2PLRwZYQ== + import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" @@ -1475,16 +966,6 @@ imurmurhash@^0.1.4: resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= -indent-string@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" - integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== - -infer-owner@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" - integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== - inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -1493,7 +974,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.3, inherits@~2.0.3: +inherits@2: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -1507,16 +988,6 @@ internal-slot@^1.0.3: has "^1.0.3" side-channel "^1.0.4" -ip@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" - integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= - is-bigint@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" @@ -1524,6 +995,13 @@ is-bigint@^1.0.1: dependencies: has-bigints "^1.0.1" +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + is-boolean-object@^1.1.0: version "1.1.2" resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" @@ -1537,7 +1015,7 @@ is-callable@^1.1.4, is-callable@^1.2.4: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== -is-core-module@^2.2.0, is-core-module@^2.5.0, is-core-module@^2.8.0, is-core-module@^2.8.1: +is-core-module@^2.2.0, is-core-module@^2.8.0, is-core-module@^2.8.1: version "2.8.1" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== @@ -1556,23 +1034,13 @@ is-extglob@^2.1.1: resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== dependencies: is-extglob "^2.1.1" -is-lambda@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" - integrity sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU= - is-negative-zero@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" @@ -1590,11 +1058,6 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== -is-plain-obj@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= - is-regex@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" @@ -1622,11 +1085,6 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" -is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= - is-weakref@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" @@ -1634,27 +1092,12 @@ is-weakref@^1.0.1: dependencies: call-bind "^1.0.2" -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= - -js-base64@^2.4.3: - version "2.6.4" - resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.6.4.tgz#f4e686c5de1ea1f867dbcad3d46d969428df98c4" - integrity sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ== - -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: +"js-tokens@^3.0.0 || ^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== @@ -1666,53 +1109,23 @@ js-yaml@^4.1.0: dependencies: argparse "^2.0.1" -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= - -json-parse-even-better-errors@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== -json-schema@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" - integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== - json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= -json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= - json5@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + version "1.0.2" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" + integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== dependencies: minimist "^1.2.0" -jsprim@^1.2.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" - integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.4.0" - verror "1.10.0" - "jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.2.1.tgz#720b97bfe7d901b927d87c3773637ae8ea48781b" @@ -1721,11 +1134,6 @@ jsprim@^1.2.2: array-includes "^3.1.3" object.assign "^4.1.2" -kind-of@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" - integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== - language-subtag-registry@~0.3.2: version "0.3.21" resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz#04ac218bea46f04cb039084602c6da9e788dd45a" @@ -1746,11 +1154,6 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" -lines-and-columns@^1.1.6: - version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" - integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== - locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" @@ -1759,23 +1162,11 @@ locate-path@^2.0.0: p-locate "^2.0.0" path-exists "^3.0.0" -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash@^4.17.11, lodash@^4.17.15, lodash@~4.17.10: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - loose-envify@^1.1.0, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" @@ -1790,56 +1181,6 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" -make-fetch-happen@^9.1.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz#53085a09e7971433e6765f7971bf63f4e05cb968" - integrity sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg== - dependencies: - agentkeepalive "^4.1.3" - cacache "^15.2.0" - http-cache-semantics "^4.1.0" - http-proxy-agent "^4.0.1" - https-proxy-agent "^5.0.0" - is-lambda "^1.0.1" - lru-cache "^6.0.0" - minipass "^3.1.3" - minipass-collect "^1.0.2" - minipass-fetch "^1.3.2" - minipass-flush "^1.0.5" - minipass-pipeline "^1.2.4" - negotiator "^0.6.2" - promise-retry "^2.0.1" - socks-proxy-agent "^6.0.0" - ssri "^8.0.0" - -map-obj@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" - integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= - -map-obj@^4.0.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a" - integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ== - -meow@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/meow/-/meow-9.0.0.tgz#cd9510bc5cac9dee7d03c73ee1f9ad959f4ea364" - integrity sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ== - dependencies: - "@types/minimist" "^1.2.0" - camelcase-keys "^6.2.2" - decamelize "^1.2.0" - decamelize-keys "^1.1.0" - hard-rejection "^2.1.0" - minimist-options "4.1.0" - normalize-package-data "^3.0.0" - read-pkg-up "^7.0.1" - redent "^3.0.0" - trim-newlines "^3.0.0" - type-fest "^0.18.0" - yargs-parser "^20.2.3" - merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" @@ -1853,23 +1194,6 @@ micromatch@^4.0.4: braces "^3.0.1" picomatch "^2.2.3" -mime-db@1.51.0: - version "1.51.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" - integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== - -mime-types@^2.1.12, mime-types@~2.1.19: - version "2.1.34" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" - integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== - dependencies: - mime-db "1.51.0" - -min-indent@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" - integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== - minimatch@^3.0.4, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -1877,85 +1201,10 @@ minimatch@^3.0.4, minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" -minimatch@~3.0.2: - version "3.0.8" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.8.tgz#5e6a59bd11e2ab0de1cfb843eb2d82e546c321c1" - integrity sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q== - dependencies: - brace-expansion "^1.1.7" - -minimist-options@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" - integrity sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A== - dependencies: - arrify "^1.0.1" - is-plain-obj "^1.1.0" - kind-of "^6.0.3" - minimist@^1.2.0: - version "1.2.6" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" - integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== - -minipass-collect@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617" - integrity sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA== - dependencies: - minipass "^3.0.0" - -minipass-fetch@^1.3.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-1.4.1.tgz#d75e0091daac1b0ffd7e9d41629faff7d0c1f1b6" - integrity sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw== - dependencies: - minipass "^3.1.0" - minipass-sized "^1.0.3" - minizlib "^2.0.0" - optionalDependencies: - encoding "^0.1.12" - -minipass-flush@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373" - integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw== - dependencies: - minipass "^3.0.0" - -minipass-pipeline@^1.2.2, minipass-pipeline@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c" - integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== - dependencies: - minipass "^3.0.0" - -minipass-sized@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/minipass-sized/-/minipass-sized-1.0.3.tgz#70ee5a7c5052070afacfbc22977ea79def353b70" - integrity sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g== - dependencies: - minipass "^3.0.0" - -minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3: - version "3.1.6" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.6.tgz#3b8150aa688a711a1521af5e8779c1d3bb4f45ee" - integrity sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ== - dependencies: - yallist "^4.0.0" - -minizlib@^2.0.0, minizlib@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" - integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== - dependencies: - minipass "^3.0.0" - yallist "^4.0.0" - -mkdirp@^1.0.3, mkdirp@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" - integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + version "1.2.7" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" + integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== ms@2.0.0: version "2.0.0" @@ -1967,16 +1216,11 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@^2.0.0, ms@^2.1.1: +ms@^2.1.1: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -nan@^2.13.2: - version "2.15.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" - integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ== - nanoid@^3.1.30: version "3.3.1" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" @@ -1987,11 +1231,6 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= -negotiator@^0.6.2: - version "0.6.3" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" - integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== - next@12.1.0: version "12.1.0" resolved "https://registry.yarnpkg.com/next/-/next-12.1.0.tgz#c33d753b644be92fc58e06e5a214f143da61dd5d" @@ -2029,94 +1268,10 @@ node-fetch@^3.2.10: fetch-blob "^3.1.4" formdata-polyfill "^4.0.10" -node-gyp@^8.4.1: - version "8.4.1" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-8.4.1.tgz#3d49308fc31f768180957d6b5746845fbd429937" - integrity sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w== - dependencies: - env-paths "^2.2.0" - glob "^7.1.4" - graceful-fs "^4.2.6" - make-fetch-happen "^9.1.0" - nopt "^5.0.0" - npmlog "^6.0.0" - rimraf "^3.0.2" - semver "^7.3.5" - tar "^6.1.2" - which "^2.0.2" - -node-sass@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-7.0.1.tgz#ad4f6bc663de8acc0a9360db39165a1e2620aa72" - integrity sha512-uMy+Xt29NlqKCFdFRZyXKOTqGt+QaKHexv9STj2WeLottnlqZEEWx6Bj0MXNthmFRRdM/YwyNo/8Tr46TOM0jQ== - dependencies: - async-foreach "^0.1.3" - chalk "^4.1.2" - cross-spawn "^7.0.3" - gaze "^1.0.0" - get-stdin "^4.0.1" - glob "^7.0.3" - lodash "^4.17.15" - meow "^9.0.0" - nan "^2.13.2" - node-gyp "^8.4.1" - npmlog "^5.0.0" - request "^2.88.0" - sass-graph "4.0.0" - stdout-stream "^1.4.0" - "true-case-path" "^1.0.2" - -nopt@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" - integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ== - dependencies: - abbrev "1" - -normalize-package-data@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" - integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== - dependencies: - hosted-git-info "^2.1.4" - resolve "^1.10.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - -normalize-package-data@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-3.0.3.tgz#dbcc3e2da59509a0983422884cd172eefdfa525e" - integrity sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA== - dependencies: - hosted-git-info "^4.0.1" - is-core-module "^2.5.0" - semver "^7.3.4" - validate-npm-package-license "^3.0.1" - -npmlog@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-5.0.1.tgz#f06678e80e29419ad67ab964e0fa69959c1eb8b0" - integrity sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw== - dependencies: - are-we-there-yet "^2.0.0" - console-control-strings "^1.1.0" - gauge "^3.0.0" - set-blocking "^2.0.0" - -npmlog@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-6.0.1.tgz#06f1344a174c06e8de9c6c70834cfba2964bba17" - integrity sha512-BTHDvY6nrRHuRfyjt1MAufLxYdVXZfd099H4+i1f0lPywNQyI4foeNXJRObB/uy+TYqUW0vAD9gbdSOXPst7Eg== - dependencies: - are-we-there-yet "^3.0.0" - console-control-strings "^1.1.0" - gauge "^4.0.0" - set-blocking "^2.0.0" - -oauth-sign@~0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" - integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== object-assign@^4.1.1: version "4.1.1" @@ -2204,13 +1359,6 @@ p-limit@^1.1.0: dependencies: p-try "^1.0.0" -p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" @@ -2218,30 +1366,11 @@ p-locate@^2.0.0: dependencies: p-limit "^1.1.0" -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - -p-map@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" - integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== - dependencies: - aggregate-error "^3.0.0" - p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -2249,26 +1378,11 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parse-json@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" - integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== - dependencies: - "@babel/code-frame" "^7.0.0" - error-ex "^1.3.1" - json-parse-even-better-errors "^2.3.0" - lines-and-columns "^1.1.6" - path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -2289,17 +1403,12 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= - picocolors@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.2.3: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -2318,24 +1427,6 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -promise-inflight@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" - integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= - -promise-retry@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-2.0.1.tgz#ff747a13620ab57ba688f5fc67855410c370da22" - integrity sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g== - dependencies: - err-code "^2.0.2" - retry "^0.12.0" - prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" @@ -2345,31 +1436,16 @@ prop-types@^15.8.1: object-assign "^4.1.1" react-is "^16.13.1" -psl@^1.1.28: - version "1.8.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" - integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== - -punycode@^2.1.0, punycode@^2.1.1: +punycode@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== -qs@~6.5.2: - version "6.5.3" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" - integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== - queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== -quick-lru@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" - integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g== - react-dom@17.0.2: version "17.0.2" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23" @@ -2397,54 +1473,12 @@ react@17.0.2: loose-envify "^1.1.0" object-assign "^4.1.1" -read-pkg-up@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" - integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== - dependencies: - find-up "^4.1.0" - read-pkg "^5.2.0" - type-fest "^0.8.1" - -read-pkg@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" - integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== - dependencies: - "@types/normalize-package-data" "^2.4.0" - normalize-package-data "^2.5.0" - parse-json "^5.0.0" - type-fest "^0.6.0" - -readable-stream@^2.0.1: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@^3.6.0: +readdirp@~3.6.0: version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -redent@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" - integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== - dependencies: - indent-string "^4.0.0" - strip-indent "^3.0.0" + picomatch "^2.2.1" regenerator-runtime@^0.13.4: version "0.13.9" @@ -2464,43 +1498,12 @@ regexpp@^3.2.0: resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== -request@^2.88.0: - version "2.88.2" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" - integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.8.0" - caseless "~0.12.0" - combined-stream "~1.0.6" - extend "~3.0.2" - forever-agent "~0.6.1" - form-data "~2.3.2" - har-validator "~5.1.3" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.19" - oauth-sign "~0.9.0" - performance-now "^2.1.0" - qs "~6.5.2" - safe-buffer "^5.1.2" - tough-cookie "~2.5.0" - tunnel-agent "^0.6.0" - uuid "^3.3.2" - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= - resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== -resolve@^1.10.0, resolve@^1.20.0: +resolve@^1.20.0: version "1.22.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== @@ -2517,11 +1520,6 @@ resolve@^2.0.0-next.3: is-core-module "^2.2.0" path-parse "^1.0.6" -retry@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" - integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= - reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" @@ -2541,30 +1539,14 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -"safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -sass-graph@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-4.0.0.tgz#fff8359efc77b31213056dfd251d05dadc74c613" - integrity sha512-WSO/MfXqKH7/TS8RdkCX3lVkPFQzCgbqdGsmSKq6tlPU+GpGEsa/5aW18JqItnqh+lPtcjifqdZ/VmiILkKckQ== +sass@^1.52.3: + version "1.57.1" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.57.1.tgz#dfafd46eb3ab94817145e8825208ecf7281119b5" + integrity sha512-O2+LwLS79op7GI0xZ8fqzF7X2m/m8WFfI02dHOdsK5R2ECeS5F62zrwg/relM1rjSLy7Vd/DiMNIvPrQGsA0jw== dependencies: - glob "^7.0.0" - lodash "^4.17.11" - scss-tokenizer "^0.3.0" - yargs "^17.2.1" + chokidar ">=3.0.0 <4.0.0" + immutable "^4.0.0" + source-map-js ">=0.6.2 <2.0.0" scheduler@^0.20.2: version "0.20.2" @@ -2574,36 +1556,18 @@ scheduler@^0.20.2: loose-envify "^1.1.0" object-assign "^4.1.1" -scss-tokenizer@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.3.0.tgz#ef7edc3bc438b25cd6ffacf1aa5b9ad5813bf260" - integrity sha512-14Zl9GcbBvOT9057ZKjpz5yPOyUWG2ojd9D5io28wHRYsOrs7U95Q+KNL87+32p8rc+LvDpbu/i9ZYjM9Q+FsQ== - dependencies: - js-base64 "^2.4.3" - source-map "^0.7.1" - -"semver@2 || 3 || 4 || 5": - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@^7.3.4, semver@^7.3.5: +semver@^7.3.5: version "7.3.5" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== dependencies: lru-cache "^6.0.0" -set-blocking@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= - shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -2625,112 +1589,16 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" -signal-exit@^3.0.0, signal-exit@^3.0.7: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== - slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -smart-buffer@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" - integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== - -socks-proxy-agent@^6.0.0: - version "6.1.1" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz#e664e8f1aaf4e1fb3df945f09e3d94f911137f87" - integrity sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew== - dependencies: - agent-base "^6.0.2" - debug "^4.3.1" - socks "^2.6.1" - -socks@^2.6.1: - version "2.6.2" - resolved "https://registry.yarnpkg.com/socks/-/socks-2.6.2.tgz#ec042d7960073d40d94268ff3bb727dc685f111a" - integrity sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA== - dependencies: - ip "^1.1.5" - smart-buffer "^4.2.0" - -source-map-js@^1.0.1: +"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== -source-map@^0.7.1: - version "0.7.3" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" - integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== - -spdx-correct@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" - integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" - integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== - -spdx-expression-parse@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" - integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^3.0.0: - version "3.0.11" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz#50c0d8c40a14ec1bf449bae69a0ea4685a9d9f95" - integrity sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g== - -sshpk@^1.7.0: - version "1.17.0" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" - integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - bcrypt-pbkdf "^1.0.0" - dashdash "^1.12.0" - ecc-jsbn "~0.1.1" - getpass "^0.1.1" - jsbn "~0.1.0" - safer-buffer "^2.0.2" - tweetnacl "~0.14.0" - -ssri@^8.0.0, ssri@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.1.tgz#638e4e439e2ffbd2cd289776d5ca457c4f51a2af" - integrity sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ== - dependencies: - minipass "^3.1.1" - -stdout-stream@^1.4.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.1.tgz#5ac174cdd5cd726104aa0c0b2bd83815d8d535de" - integrity sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA== - dependencies: - readable-stream "^2.0.1" - -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string.prototype.matchall@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.6.tgz#5abb5dabc94c7b0ea2380f65ba610b3a544b15fa" @@ -2761,21 +1629,7 @@ string.prototype.trimstart@^1.0.4: call-bind "^1.0.2" define-properties "^1.1.3" -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: +strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -2787,13 +1641,6 @@ strip-bom@^3.0.0: resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= -strip-indent@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" - integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== - dependencies: - min-indent "^1.0.0" - strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" @@ -2804,13 +1651,6 @@ styled-jsx@5.0.0: resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.0.tgz#816b4b92e07b1786c6b7111821750e0ba4d26e77" integrity sha512-qUqsWoBquEdERe10EW8vLp3jT25s/ssG1/qX5gZ4wu15OZpmSMFI2v+fWlRhLfykA5rFtlJ1ME8A8pm/peV4WA== -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" @@ -2823,18 +1663,6 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== -tar@^6.0.2, tar@^6.1.2: - version "6.1.11" - resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" - integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA== - dependencies: - chownr "^2.0.0" - fs-minipass "^2.0.0" - minipass "^3.0.0" - minizlib "^2.1.1" - mkdirp "^1.0.3" - yallist "^4.0.0" - text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -2847,26 +1675,6 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -tough-cookie@~2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" - integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== - dependencies: - psl "^1.1.28" - punycode "^2.1.1" - -trim-newlines@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144" - integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw== - -"true-case-path@^1.0.2": - version "1.0.3" - resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-1.0.3.tgz#f813b5a8c86b40da59606722b144e3225799f47d" - integrity sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew== - dependencies: - glob "^7.1.2" - tsconfig-paths@^3.12.0, tsconfig-paths@^3.9.0: version "3.13.0" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.13.0.tgz#f3e9b8f6876698581d94470c03c95b3a48c0e3d7" @@ -2889,18 +1697,6 @@ tsutils@^3.21.0: dependencies: tslib "^1.8.1" -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= - dependencies: - safe-buffer "^5.0.1" - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= - type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" @@ -2908,26 +1704,11 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" -type-fest@^0.18.0: - version "0.18.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f" - integrity sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw== - type-fest@^0.20.2: version "0.20.2" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== -type-fest@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" - integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== - -type-fest@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" - integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== - typescript@4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.2.tgz#fe12d2727b708f4eef40f51598b3398baa9611d4" @@ -2943,20 +1724,6 @@ unbox-primitive@^1.0.1: has-symbols "^1.0.2" which-boxed-primitive "^1.0.2" -unique-filename@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" - integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== - dependencies: - unique-slug "^2.0.0" - -unique-slug@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" - integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== - dependencies: - imurmurhash "^0.1.4" - uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -2971,38 +1738,11 @@ use-subscription@1.5.1: dependencies: object-assign "^4.1.1" -util-deprecate@^1.0.1, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -uuid@^3.3.2: - version "3.4.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" - integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== - v8-compile-cache@^2.0.3: version "2.3.0" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== -validate-npm-package-license@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" - -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - web-streams-polyfill@^3.0.3: version "3.2.0" resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz#a6b74026b38e4885869fb5c589e90b95ccfc7965" @@ -3019,68 +1759,24 @@ which-boxed-primitive@^1.0.2: is-string "^1.0.5" is-symbol "^1.0.3" -which@^2.0.1, which@^2.0.2: +which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== dependencies: isexe "^2.0.0" -wide-align@^1.1.2, wide-align@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" - integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== - dependencies: - string-width "^1.0.2 || 2 || 3 || 4" - word-wrap@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -y18n@^5.0.5: - version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" - integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== - yallist@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yargs-parser@^20.2.3: - version "20.2.9" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" - integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== - -yargs-parser@^21.0.0: - version "21.0.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.0.1.tgz#0267f286c877a4f0f728fceb6f8a3e4cb95c6e35" - integrity sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg== - -yargs@^17.2.1: - version "17.3.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.3.1.tgz#da56b28f32e2fd45aefb402ed9c26f42be4c07b9" - integrity sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA== - dependencies: - cliui "^7.0.2" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.3" - y18n "^5.0.5" - yargs-parser "^21.0.0" diff --git a/hosting/docker-compose.dev.yaml b/hosting/docker-compose.dev.yaml index 1626d520b6..7906a389fa 100644 --- a/hosting/docker-compose.dev.yaml +++ b/hosting/docker-compose.dev.yaml @@ -6,7 +6,8 @@ services: minio-service: container_name: budi-minio-dev restart: on-failure - image: minio/minio + # Last version that supports the "fs" backend + image: minio/minio:RELEASE.2022-10-24T18-35-07Z volumes: - minio_data:/data ports: diff --git a/hosting/nginx.dev.conf b/hosting/nginx.dev.conf index bfe30ba369..1ecee422cd 100644 --- a/hosting/nginx.dev.conf +++ b/hosting/nginx.dev.conf @@ -186,6 +186,26 @@ http { proxy_pass http://minio-service:9000; } + location /files/signed/ { + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # IMPORTANT: Signed urls will inspect the host header of the request. + # Normally a signed url will need to be generated with a specified client host in mind. + # To support dynamic hosts, e.g. some unknown self-hosted installation url, + # use a predefined host header. The host 'minio-service' is also used at the time of url signing. + proxy_set_header Host minio-service; + + proxy_connect_timeout 300; + proxy_http_version 1.1; + proxy_set_header Connection ""; + chunked_transfer_encoding off; + + proxy_pass http://minio-service:9000; + rewrite ^/files/signed/(.*)$ /$1 break; + } + client_header_timeout 60; client_body_timeout 60; keepalive_timeout 60; diff --git a/hosting/proxy/nginx.prod.conf b/hosting/proxy/nginx.prod.conf index a39b8dc803..fc2f51370b 100644 --- a/hosting/proxy/nginx.prod.conf +++ b/hosting/proxy/nginx.prod.conf @@ -202,6 +202,26 @@ http { proxy_pass $minio; } + location /files/signed/ { + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # IMPORTANT: Signed urls will inspect the host header of the request. + # Normally a signed url will need to be generated with a specified client host in mind. + # To support dynamic hosts, e.g. some unknown self-hosted installation url, + # use a predefined host header. The host 'minio-service' is also used at the time of url signing. + proxy_set_header Host minio-service; + + proxy_connect_timeout 300; + proxy_http_version 1.1; + proxy_set_header Connection ""; + chunked_transfer_encoding off; + + proxy_pass $minio; + rewrite ^/files/signed/(.*)$ /$1 break; + } + client_header_timeout 60; client_body_timeout 60; keepalive_timeout 60; diff --git a/hosting/single/nginx/nginx-default-site.conf b/hosting/single/nginx/nginx-default-site.conf index acadb06250..3903c0647d 100644 --- a/hosting/single/nginx/nginx-default-site.conf +++ b/hosting/single/nginx/nginx-default-site.conf @@ -95,15 +95,37 @@ server { } location / { - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $http_host; - proxy_connect_timeout 300; - proxy_http_version 1.1; - proxy_set_header Connection ""; - chunked_transfer_encoding off; - proxy_pass http://127.0.0.1:9000; + proxy_connect_timeout 300; + proxy_http_version 1.1; + proxy_set_header Connection ""; + chunked_transfer_encoding off; + + proxy_pass http://127.0.0.1:9000; + } + + location /files/signed/ { + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # IMPORTANT: Signed urls will inspect the host header of the request. + # Normally a signed url will need to be generated with a specified client host in mind. + # To support dynamic hosts, e.g. some unknown self-hosted installation url, + # use a predefined host header. The host 'minio-service' is also used at the time of url signing. + proxy_set_header Host minio-service; + + proxy_connect_timeout 300; + proxy_http_version 1.1; + proxy_set_header Connection ""; + chunked_transfer_encoding off; + + proxy_pass http://127.0.0.1:9000; + rewrite ^/files/signed/(.*)$ /$1 break; } client_header_timeout 60; diff --git a/hosting/single/runner.sh b/hosting/single/runner.sh index 6eebba62b6..3a28cd6e4f 100644 --- a/hosting/single/runner.sh +++ b/hosting/single/runner.sh @@ -10,7 +10,7 @@ declare -a DOCKER_VARS=("APP_PORT" "APPS_URL" "ARCHITECTURE" "BUDIBASE_ENVIRONME [[ -z "${MINIO_URL}" ]] && export MINIO_URL=http://localhost:9000 [[ -z "${NODE_ENV}" ]] && export NODE_ENV=production [[ -z "${POSTHOG_TOKEN}" ]] && export POSTHOG_TOKEN=phc_bIjZL7oh2GEUd2vqvTBH8WvrX0fWTFQMs6H5KQxiUxU -[[ -z "${TENANT_FEATURE_FLAGS}" ]] && export TENANT_FEATURE_FLAGS="*:LICENSING,*:USER_GROUPS" +[[ -z "${TENANT_FEATURE_FLAGS}" ]] && export TENANT_FEATURE_FLAGS="*:LICENSING,*:USER_GROUPS,*:ONBOARDING_TOUR" [[ -z "${ACCOUNT_PORTAL_URL}" ]] && export ACCOUNT_PORTAL_URL=https://account.budibase.app [[ -z "${REDIS_URL}" ]] && export REDIS_URL=localhost:6379 [[ -z "${SELF_HOSTED}" ]] && export SELF_HOSTED=1 diff --git a/lerna.json b/lerna.json index adbb3ef570..5d054e467b 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "2.2.26", + "version": "2.2.27-alpha.0", "npmClient": "yarn", "packages": [ "packages/*" diff --git a/package.json b/package.json index 6134ae2880..6290930269 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "bootstrap": "lerna bootstrap && lerna link && ./scripts/link-dependencies.sh", "build": "lerna run build", "build:dev": "lerna run prebuild && tsc --build --watch --preserveWatchOutput", + "build:backend": "lerna run build --ignore @budibase/client --ignore @budibase/bbui --ignore @budibase/builder --ignore @budibase/cli", "build:sdk": "lerna run build:sdk", "deps:circular": "madge packages/server/dist/index.js packages/worker/src/index.ts packages/backend-core/dist/src/index.js packages/cli/src/index.js --circular", "release": "lerna publish ${RELEASE_VERSION_TYPE:-patch} --yes --force-publish && yarn release:pro", @@ -44,16 +45,12 @@ "dev:server": "yarn run kill-server && lerna run --parallel dev:builder --concurrency 1 --scope @budibase/backend-core --scope @budibase/worker --scope @budibase/server", "test": "lerna run test && yarn test:pro", "test:pro": "bash scripts/pro/test.sh", - "lint:eslint": "eslint packages", - "lint:prettier": "prettier --check \"packages/**/*.{js,ts,svelte}\"", + "lint:eslint": "eslint packages && eslint qa-core", + "lint:prettier": "prettier --check \"packages/**/*.{js,ts,svelte}\" && prettier --write \"examples/**/*.{js,ts,svelte}\" && prettier --check \"qa-core/**/*.{js,ts,svelte}\"", "lint": "yarn run lint:eslint && yarn run lint:prettier", "lint:fix:eslint": "eslint --fix packages qa-core", "lint:fix:prettier": "prettier --write \"packages/**/*.{js,ts,svelte}\" && prettier --write \"examples/**/*.{js,ts,svelte}\" && prettier --write \"qa-core/**/*.{js,ts,svelte}\"", "lint:fix": "yarn run lint:fix:prettier && yarn run lint:fix:eslint", - "test:e2e": "lerna run cy:test --stream", - "test:e2e:ci": "lerna run cy:ci --stream", - "test:e2e:ci:record": "lerna run cy:ci:record --stream", - "test:e2e:ci:notify": "lerna run cy:ci:notify", "build:specs": "lerna run specs", "build:docker": "lerna run build:docker && npm run build:docker:proxy && cd hosting/scripts/linux/ && ./release-to-docker-hub.sh $BUDIBASE_RELEASE_VERSION && cd -", "build:docker:pre": "lerna run build && lerna run predocker", diff --git a/packages/backend-core/__mocks__/aws-sdk.ts b/packages/backend-core/__mocks__/aws-sdk.ts index 7fac80faa9..b8d91dbaa9 100644 --- a/packages/backend-core/__mocks__/aws-sdk.ts +++ b/packages/backend-core/__mocks__/aws-sdk.ts @@ -3,7 +3,10 @@ const mockS3 = { deleteObject: jest.fn().mockReturnThis(), deleteObjects: jest.fn().mockReturnThis(), createBucket: jest.fn().mockReturnThis(), - listObjects: jest.fn().mockReturnThis(), + listObject: jest.fn().mockReturnThis(), + getSignedUrl: jest.fn((operation: string, params: any) => { + return `http://s3.example.com/${params.Bucket}/${params.Key}` + }), promise: jest.fn().mockReturnThis(), catch: jest.fn(), } diff --git a/packages/backend-core/jest.config.ts b/packages/backend-core/jest.config.ts index d0e5d3d4e7..e5993f6596 100644 --- a/packages/backend-core/jest.config.ts +++ b/packages/backend-core/jest.config.ts @@ -6,6 +6,9 @@ const config: Config.InitialOptions = { setupFiles: ["./tests/jestSetup.ts"], collectCoverageFrom: ["src/**/*.{js,ts}"], coverageReporters: ["lcov", "json", "clover"], + transform: { + "^.+\\.ts?$": "@swc/jest", + }, } if (!process.env.CI) { diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json index 67d9deeac2..342ec82319 100644 --- a/packages/backend-core/package.json +++ b/packages/backend-core/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/backend-core", - "version": "2.2.26", + "version": "2.2.27-alpha.0", "description": "Budibase backend core libraries used in server and worker", "main": "dist/src/index.js", "types": "dist/src/index.d.ts", @@ -15,24 +15,28 @@ "prebuild": "rimraf dist/", "prepack": "cp package.json dist", "build": "tsc -p tsconfig.build.json", + "build:pro": "../../scripts/pro/build.sh", + "postbuild": "yarn run build:pro", "build:dev": "yarn prebuild && tsc --build --watch --preserveWatchOutput", "test": "jest --coverage --maxWorkers=2", "test:watch": "jest --watchAll" }, "dependencies": { "@budibase/nano": "10.1.1", - "@budibase/types": "^2.2.26", + "@budibase/types": "2.2.27-alpha.0", "@shopify/jest-koa-mocks": "5.0.1", "@techpass/passport-openidconnect": "0.3.2", + "aws-cloudfront-sign": "2.2.0", "aws-sdk": "2.1030.0", "bcrypt": "5.0.1", "bcryptjs": "2.4.3", "bull": "4.10.1", + "correlation-id": "4.0.0", "dotenv": "16.0.1", "emitter-listener": "1.1.2", "ioredis": "4.28.0", "joi": "17.6.0", - "jsonwebtoken": "8.5.1", + "jsonwebtoken": "9.0.0", "koa-passport": "4.1.4", "lodash": "4.17.21", "lodash.isarguments": "3.1.0", @@ -53,19 +57,23 @@ "zlib": "1.0.5" }, "devDependencies": { + "@swc/core": "^1.3.25", + "@swc/jest": "^0.2.24", "@types/chance": "1.1.3", "@types/ioredis": "4.28.0", "@types/jest": "27.5.1", "@types/koa": "2.13.4", + "@types/koa-pino-logger": "3.0.0", "@types/lodash": "4.14.180", "@types/node": "14.18.20", "@types/node-fetch": "2.6.1", + "@types/pino-http": "5.8.1", "@types/pouchdb": "6.4.0", "@types/redlock": "4.0.3", "@types/semver": "7.3.7", "@types/tar-fs": "2.0.1", "@types/uuid": "8.3.4", - "chance": "1.1.3", + "chance": "1.1.8", "ioredis-mock": "5.8.0", "jest": "28.1.1", "koa": "2.13.4", diff --git a/packages/backend-core/src/cache/base/index.ts b/packages/backend-core/src/cache/base/index.ts index ab620a900e..264984c6a5 100644 --- a/packages/backend-core/src/cache/base/index.ts +++ b/packages/backend-core/src/cache/base/index.ts @@ -7,7 +7,7 @@ function generateTenantKey(key: string) { return `${key}:${tenantId}` } -export = class BaseCache { +export default class BaseCache { client: Client | undefined constructor(client: Client | undefined = undefined) { diff --git a/packages/backend-core/src/cache/generic.ts b/packages/backend-core/src/cache/generic.ts index d8a54e4a3f..7cd5d6227f 100644 --- a/packages/backend-core/src/cache/generic.ts +++ b/packages/backend-core/src/cache/generic.ts @@ -1,6 +1,6 @@ const BaseCache = require("./base") -const GENERIC = new BaseCache() +const GENERIC = new BaseCache.default() export enum CacheKey { CHECKLIST = "checklist", diff --git a/packages/backend-core/src/cloud/api.ts b/packages/backend-core/src/cloud/api.ts index 287c447271..ef9b9d88e6 100644 --- a/packages/backend-core/src/cloud/api.ts +++ b/packages/backend-core/src/cloud/api.ts @@ -1,6 +1,7 @@ import fetch from "node-fetch" +import * as logging from "../logging" -export = class API { +export default class API { host: string constructor(host: string) { @@ -22,6 +23,9 @@ export = class API { let json = options.headers["Content-Type"] === "application/json" + // add x-budibase-correlation-id header + logging.correlation.setHeader(options.headers) + const requestOptions = { method: method, body: json ? JSON.stringify(options.body) : options.body, diff --git a/packages/backend-core/src/constants/db.ts b/packages/backend-core/src/constants/db.ts index 92392457d6..f7d15b3880 100644 --- a/packages/backend-core/src/constants/db.ts +++ b/packages/backend-core/src/constants/db.ts @@ -77,6 +77,7 @@ export const StaticDatabases = { apiKeys: "apikeys", usageQuota: "usage_quota", licenseInfo: "license_info", + environmentVariables: "environmentvariables", }, }, // contains information about tenancy and so on diff --git a/packages/backend-core/src/constants/misc.ts b/packages/backend-core/src/constants/misc.ts index 61b3cea1f6..0bf3df4094 100644 --- a/packages/backend-core/src/constants/misc.ts +++ b/packages/backend-core/src/constants/misc.ts @@ -22,6 +22,7 @@ export enum Header { TENANT_ID = "x-budibase-tenant-id", TOKEN = "x-budibase-token", CSRF_TOKEN = "x-csrf-token", + CORRELATION_ID = "x-budibase-correlation-id", } export enum GlobalRole { diff --git a/packages/backend-core/src/context/Context.ts b/packages/backend-core/src/context/Context.ts index f0ccdb97a8..02b7713764 100644 --- a/packages/backend-core/src/context/Context.ts +++ b/packages/backend-core/src/context/Context.ts @@ -1,17 +1,14 @@ import { AsyncLocalStorage } from "async_hooks" +import { ContextMap } from "./mainContext" export default class Context { - static storage = new AsyncLocalStorage>() + static storage = new AsyncLocalStorage() - static run(context: Record, func: any) { + static run(context: ContextMap, func: any) { return Context.storage.run(context, () => func()) } - static get(): Record { - return Context.storage.getStore() as Record - } - - static set(context: Record) { - Context.storage.enterWith(context) + static get(): ContextMap { + return Context.storage.getStore() as ContextMap } } diff --git a/packages/backend-core/src/context/mainContext.ts b/packages/backend-core/src/context/mainContext.ts index d743d2f49b..9884d25d5a 100644 --- a/packages/backend-core/src/context/mainContext.ts +++ b/packages/backend-core/src/context/mainContext.ts @@ -2,7 +2,7 @@ // store an app ID to pretend there is a context import env from "../environment" import Context from "./Context" -import { getDevelopmentAppID, getProdAppID } from "../db/conversions" +import * as conversions from "../db/conversions" import { getDB } from "../db/db" import { DocumentType, @@ -16,6 +16,7 @@ export type ContextMap = { tenantId?: string appId?: string identity?: IdentityContext + environmentVariables?: Record } let TEST_APP_ID: string | null = null @@ -75,7 +76,7 @@ export function getTenantIDFromAppID(appId: string) { } } -function updateContext(updates: ContextMap) { +function updateContext(updates: ContextMap): ContextMap { let context: ContextMap try { context = Context.get() @@ -120,15 +121,23 @@ export async function doInTenant( return newContext(updates, task) } -export async function doInAppContext(appId: string, task: any): Promise { - if (!appId) { +export async function doInAppContext( + appId: string | null, + task: any +): Promise { + if (!appId && !env.isTest()) { throw new Error("appId is required") } - const tenantId = getTenantIDFromAppID(appId) - const updates: ContextMap = { appId } - if (tenantId) { - updates.tenantId = tenantId + let updates: ContextMap + if (!appId) { + updates = { appId: "" } + } else { + const tenantId = getTenantIDFromAppID(appId) + updates = { appId } + if (tenantId) { + updates.tenantId = tenantId + } } return newContext(updates, task) } @@ -181,25 +190,33 @@ export function getAppId(): string | undefined { } } -export function updateTenantId(tenantId?: string) { - let context: ContextMap = updateContext({ - tenantId, - }) - Context.set(context) +export const getProdAppId = () => { + const appId = getAppId() + if (!appId) { + throw new Error("Could not get appId") + } + return conversions.getProdAppID(appId) } -export function updateAppId(appId: string) { - let context: ContextMap = updateContext({ - appId, - }) - try { - Context.set(context) - } catch (err) { - if (env.isTest()) { - TEST_APP_ID = appId - } else { - throw err - } +export function doInEnvironmentContext( + values: Record, + task: any +) { + if (!values) { + throw new Error("Must supply environment variables.") + } + const updates = { + environmentVariables: values, + } + return newContext(updates, task) +} + +export function getEnvironmentVariables() { + const context = Context.get() + if (!context.environmentVariables) { + return null + } else { + return context.environmentVariables } } @@ -229,7 +246,7 @@ export function getProdAppDB(opts?: any): Database { if (!appId) { throw new Error("Unable to retrieve prod DB - no app ID.") } - return getDB(getProdAppID(appId), opts) + return getDB(conversions.getProdAppID(appId), opts) } /** @@ -241,5 +258,5 @@ export function getDevAppDB(opts?: any): Database { if (!appId) { throw new Error("Unable to retrieve dev DB - no app ID.") } - return getDB(getDevelopmentAppID(appId), opts) + return getDB(conversions.getDevelopmentAppID(appId), opts) } diff --git a/packages/backend-core/src/context/tests/index.spec.js b/packages/backend-core/src/context/tests/index.spec.ts similarity index 97% rename from packages/backend-core/src/context/tests/index.spec.js rename to packages/backend-core/src/context/tests/index.spec.ts index ea60806d21..c9b5870ffa 100644 --- a/packages/backend-core/src/context/tests/index.spec.js +++ b/packages/backend-core/src/context/tests/index.spec.ts @@ -1,7 +1,7 @@ require("../../../tests") const context = require("../") const { DEFAULT_TENANT_ID } = require("../../constants") -const env = require("../../environment") +import env from "../../environment" describe("context", () => { describe("doInTenant", () => { @@ -26,7 +26,7 @@ describe("context", () => { it("fails when no tenant id is set", () => { const test = () => { - let error + let error: any try { context.getTenantId() } catch (e) { @@ -45,7 +45,7 @@ describe("context", () => { it("fails when no tenant db is set", () => { const test = () => { - let error + let error: any try { context.getGlobalDB() } catch (e) { diff --git a/packages/backend-core/src/db/couch/DatabaseImpl.ts b/packages/backend-core/src/db/couch/DatabaseImpl.ts index 9b4761d961..a60a748bdc 100644 --- a/packages/backend-core/src/db/couch/DatabaseImpl.ts +++ b/packages/backend-core/src/db/couch/DatabaseImpl.ts @@ -15,18 +15,47 @@ import { getCouchInfo } from "./connections" import { directCouchCall } from "./utils" import { getPouchDB } from "./pouchDB" import { WriteStream, ReadStream } from "fs" +import { newid } from "../../newid" + +function buildNano(couchInfo: { url: string; cookie: string }) { + return Nano({ + url: couchInfo.url, + requestDefaults: { + headers: { + Authorization: couchInfo.cookie, + }, + }, + parseUrl: false, + }) +} + +export function DatabaseWithConnection( + dbName: string, + connection: string, + opts?: DatabaseOpts +) { + if (!connection) { + throw new Error("Must provide connection details") + } + return new DatabaseImpl(dbName, opts, connection) +} export class DatabaseImpl implements Database { public readonly name: string private static nano: Nano.ServerScope + private readonly instanceNano?: Nano.ServerScope private readonly pouchOpts: DatabaseOpts - constructor(dbName?: string, opts?: DatabaseOpts) { + constructor(dbName?: string, opts?: DatabaseOpts, connection?: string) { if (dbName == null) { throw new Error("Database name cannot be undefined.") } this.name = dbName this.pouchOpts = opts || {} + if (connection) { + const couchInfo = getCouchInfo(connection) + this.instanceNano = buildNano(couchInfo) + } if (!DatabaseImpl.nano) { DatabaseImpl.init() } @@ -34,15 +63,7 @@ export class DatabaseImpl implements Database { static init() { const couchInfo = getCouchInfo() - DatabaseImpl.nano = Nano({ - url: couchInfo.url, - requestDefaults: { - headers: { - Authorization: couchInfo.cookie, - }, - }, - parseUrl: false, - }) + DatabaseImpl.nano = buildNano(couchInfo) } async exists() { @@ -50,6 +71,10 @@ export class DatabaseImpl implements Database { return response.status === 200 } + private nano() { + return this.instanceNano || DatabaseImpl.nano + } + async checkSetup() { let shouldCreate = !this.pouchOpts?.skip_setup // check exists in a lightweight fashion @@ -58,9 +83,9 @@ export class DatabaseImpl implements Database { throw new Error("DB does not exist") } if (!exists) { - await DatabaseImpl.nano.db.create(this.name) + await this.nano().db.create(this.name) } - return DatabaseImpl.nano.db.use(this.name) + return this.nano().db.use(this.name) } private async updateOutput(fnc: any) { @@ -101,6 +126,13 @@ export class DatabaseImpl implements Database { return this.updateOutput(() => db.destroy(_id, _rev)) } + async post(document: AnyDocument, opts?: DatabasePutOpts) { + if (!document._id) { + document._id = newid() + } + return this.put(document, opts) + } + async put(document: AnyDocument, opts?: DatabasePutOpts) { if (!document._id) { throw new Error("Cannot store document without _id field.") @@ -146,7 +178,7 @@ export class DatabaseImpl implements Database { async destroy() { try { - await DatabaseImpl.nano.db.destroy(this.name) + await this.nano().db.destroy(this.name) } catch (err: any) { // didn't exist, don't worry if (err.statusCode === 404) { diff --git a/packages/backend-core/src/db/couch/connections.ts b/packages/backend-core/src/db/couch/connections.ts index a2206de634..06c661f350 100644 --- a/packages/backend-core/src/db/couch/connections.ts +++ b/packages/backend-core/src/db/couch/connections.ts @@ -1,7 +1,7 @@ import env from "../../environment" -export const getCouchInfo = () => { - const urlInfo = getUrlInfo() +export const getCouchInfo = (connection?: string) => { + const urlInfo = getUrlInfo(connection) let username let password if (env.COUCH_DB_USERNAME) { diff --git a/packages/backend-core/src/db/tests/utils.spec.js b/packages/backend-core/src/db/tests/utils.spec.ts similarity index 96% rename from packages/backend-core/src/db/tests/utils.spec.js rename to packages/backend-core/src/db/tests/utils.spec.ts index f95889c1cc..37b7ce51e2 100644 --- a/packages/backend-core/src/db/tests/utils.spec.js +++ b/packages/backend-core/src/db/tests/utils.spec.ts @@ -5,18 +5,13 @@ const { isDevAppID, isProdAppID, } = require("../conversions") -const { - generateAppID, - getPlatformUrl, - getScopedConfig -} = require("../utils") +const { generateAppID, getPlatformUrl, getScopedConfig } = require("../utils") const tenancy = require("../../tenancy") const { Config, DEFAULT_TENANT_ID } = require("../../constants") -const env = require("../../environment") +import env from "../../environment" describe("utils", () => { describe("app ID manipulation", () => { - function getID() { const appId = generateAppID() const split = appId.split("_") @@ -28,42 +23,42 @@ describe("utils", () => { it("should be able to generate a new app ID", () => { expect(generateAppID().startsWith("app_")).toEqual(true) }) - + it("should be able to convert a production app ID to development", () => { const { appId, uuid } = getID() expect(getDevelopmentAppID(appId)).toEqual(`app_dev_${uuid}`) }) - + it("should be able to convert a development app ID to development", () => { const { devAppId, uuid } = getID() expect(getDevelopmentAppID(devAppId)).toEqual(`app_dev_${uuid}`) }) - + it("should be able to convert a development ID to a production", () => { const { devAppId, uuid } = getID() expect(getProdAppID(devAppId)).toEqual(`app_${uuid}`) }) - + it("should be able to convert a production ID to production", () => { const { appId, uuid } = getID() expect(getProdAppID(appId)).toEqual(`app_${uuid}`) }) - + it("should be able to confirm dev app ID is development", () => { const { devAppId } = getID() expect(isDevAppID(devAppId)).toEqual(true) }) - + it("should be able to confirm prod app ID is not development", () => { const { appId } = getID() expect(isDevAppID(appId)).toEqual(false) }) - + it("should be able to confirm prod app ID is prod", () => { const { appId } = getID() expect(isProdAppID(appId)).toEqual(true) }) - + it("should be able to confirm dev app ID is not prod", () => { const { devAppId } = getID() expect(isProdAppID(devAppId)).toEqual(false) @@ -81,8 +76,8 @@ const setDbPlatformUrl = async () => { _id: "config_settings", type: Config.SETTINGS, config: { - platformUrl: DB_URL - } + platformUrl: DB_URL, + }, }) } @@ -92,17 +87,16 @@ const clearSettingsConfig = async () => { try { const config = await db.get("config_settings") await db.remove("config_settings", config._rev) - } catch (e) { + } catch (e: any) { if (e.status !== 404) { throw e } } }) } - + describe("getPlatformUrl", () => { describe("self host", () => { - beforeEach(async () => { env._set("SELF_HOST", 1) await clearSettingsConfig() @@ -129,10 +123,9 @@ describe("getPlatformUrl", () => { const url = await getPlatformUrl() expect(url).toBe(DB_URL) }) - }) + }) }) - describe("cloud", () => { const TENANT_AWARE_URL = "http://default.env.com" @@ -163,13 +156,12 @@ describe("getPlatformUrl", () => { const url = await getPlatformUrl() expect(url).toBe(TENANT_AWARE_URL) }) - }) + }) }) }) describe("getScopedConfig", () => { describe("settings config", () => { - beforeEach(async () => { env._set("SELF_HOSTED", 1) env._set("PLATFORM_URL", "") diff --git a/packages/backend-core/src/db/utils.ts b/packages/backend-core/src/db/utils.ts index 590c3eeef8..5e501c8d22 100644 --- a/packages/backend-core/src/db/utils.ts +++ b/packages/backend-core/src/db/utils.ts @@ -14,7 +14,7 @@ import { doWithDB, allDbs, directCouchAllDbs } from "./db" import { getAppMetadata } from "../cache/appMetadata" import { isDevApp, isDevAppID, getProdAppID } from "./conversions" import * as events from "../events" -import { App, Database, ConfigType } from "@budibase/types" +import { App, Database, ConfigType, isSettingsConfig } from "@budibase/types" /** * Generates a new app ID. @@ -489,18 +489,12 @@ export const getScopedFullConfig = async function ( // custom logic for settings doc if (type === ConfigType.SETTINGS) { - if (scopedConfig && scopedConfig.doc) { - // overrides affected by environment variables - scopedConfig.doc.config.platformUrl = await getPlatformUrl({ - tenantAware: true, - }) - scopedConfig.doc.config.analyticsEnabled = - await events.analytics.enabled() - } else { + if (!scopedConfig || !scopedConfig.doc) { // defaults scopedConfig = { doc: { _id: generateConfigID({ type, user, workspace }), + type: ConfigType.SETTINGS, config: { platformUrl: await getPlatformUrl({ tenantAware: true }), analyticsEnabled: await events.analytics.enabled(), @@ -508,6 +502,16 @@ export const getScopedFullConfig = async function ( }, } } + + // will always be true - use assertion function to get type access + if (isSettingsConfig(scopedConfig.doc)) { + // overrides affected by environment + scopedConfig.doc.config.platformUrl = await getPlatformUrl({ + tenantAware: true, + }) + scopedConfig.doc.config.analyticsEnabled = + await events.analytics.enabled() + } } return scopedConfig && scopedConfig.doc diff --git a/packages/backend-core/src/environment.ts b/packages/backend-core/src/environment.ts index 51ab101b3c..d742ca1cc9 100644 --- a/packages/backend-core/src/environment.ts +++ b/packages/backend-core/src/environment.ts @@ -1,9 +1,13 @@ function isTest() { - return ( - process.env.NODE_ENV === "jest" || - process.env.NODE_ENV === "cypress" || - process.env.JEST_WORKER_ID != null - ) + return isCypress() || isJest() +} + +function isJest() { + return !!(process.env.NODE_ENV === "jest" || process.env.JEST_WORKER_ID) +} + +function isCypress() { + return process.env.NODE_ENV === "cypress" } function isDev() { @@ -21,15 +25,19 @@ const DefaultBucketName = { APPS: "prod-budi-app-assets", TEMPLATES: "templates", GLOBAL: "global", - CLOUD: "prod-budi-tenant-uploads", PLUGINS: "plugins", } const environment = { isTest, + isJest, isDev, + isProd: () => { + return !isDev() + }, JS_BCRYPT: process.env.JS_BCRYPT, JWT_SECRET: process.env.JWT_SECRET, + ENCRYPTION_KEY: process.env.ENCRYPTION_KEY, COUCH_DB_URL: process.env.COUCH_DB_URL || "http://localhost:4005", COUCH_DB_USERNAME: process.env.COUCH_DB_USER, COUCH_DB_PASSWORD: process.env.COUCH_DB_PASSWORD, @@ -42,6 +50,7 @@ const environment = { MINIO_SECRET_KEY: process.env.MINIO_SECRET_KEY, AWS_REGION: process.env.AWS_REGION, MINIO_URL: process.env.MINIO_URL, + MINIO_ENABLED: process.env.MINIO_ENABLED || 1, INTERNAL_API_KEY: process.env.INTERNAL_API_KEY, MULTI_TENANCY: process.env.MULTI_TENANCY, ACCOUNT_PORTAL_URL: @@ -54,6 +63,9 @@ const environment = { POSTHOG_TOKEN: process.env.POSTHOG_TOKEN, ENABLE_ANALYTICS: process.env.ENABLE_ANALYTICS, TENANT_FEATURE_FLAGS: process.env.TENANT_FEATURE_FLAGS, + CLOUDFRONT_CDN: process.env.CLOUDFRONT_CDN, + CLOUDFRONT_PRIVATE_KEY_64: process.env.CLOUDFRONT_PRIVATE_KEY_64, + CLOUDFRONT_PUBLIC_KEY_ID: process.env.CLOUDFRONT_PUBLIC_KEY_ID, BACKUPS_BUCKET_NAME: process.env.BACKUPS_BUCKET_NAME || DefaultBucketName.BACKUPS, APPS_BUCKET_NAME: process.env.APPS_BUCKET_NAME || DefaultBucketName.APPS, @@ -61,12 +73,9 @@ const environment = { process.env.TEMPLATES_BUCKET_NAME || DefaultBucketName.TEMPLATES, GLOBAL_BUCKET_NAME: process.env.GLOBAL_BUCKET_NAME || DefaultBucketName.GLOBAL, - GLOBAL_CLOUD_BUCKET_NAME: - process.env.GLOBAL_CLOUD_BUCKET_NAME || DefaultBucketName.CLOUD, PLUGIN_BUCKET_NAME: process.env.PLUGIN_BUCKET_NAME || DefaultBucketName.PLUGINS, USE_COUCH: process.env.USE_COUCH || true, - DISABLE_DEVELOPER_LICENSE: process.env.DISABLE_DEVELOPER_LICENSE, DEFAULT_LICENSE: process.env.DEFAULT_LICENSE, SERVICE: process.env.SERVICE || "budibase", LOG_LEVEL: process.env.LOG_LEVEL, @@ -87,6 +96,11 @@ for (let [key, value] of Object.entries(environment)) { // @ts-ignore environment[key] = 0 } + // handle the edge case of "false" to disable an environment variable + if (value === "false") { + // @ts-ignore + environment[key] = 0 + } } -export = environment +export default environment diff --git a/packages/backend-core/src/errors/errors.ts b/packages/backend-core/src/errors/errors.ts new file mode 100644 index 0000000000..83e2ab5072 --- /dev/null +++ b/packages/backend-core/src/errors/errors.ts @@ -0,0 +1,37 @@ +import * as licensing from "./licensing" + +// combine all error codes into single object + +export const codes = { + ...licensing.codes, +} + +// combine all error types +export const types = [licensing.type] + +// combine all error contexts +const context = { + ...licensing.context, +} + +// derive a public error message using codes, types and any custom contexts +export const getPublicError = (err: any) => { + let error + if (err.code || err.type) { + // add generic error information + error = { + code: err.code, + type: err.type, + } + + if (err.code && context[err.code]) { + error = { + ...error, + // get any additional context from this error + ...context[err.code](err), + } + } + } + + return error +} diff --git a/packages/backend-core/src/errors/index.ts b/packages/backend-core/src/errors/index.ts index be6657093d..814d836590 100644 --- a/packages/backend-core/src/errors/index.ts +++ b/packages/backend-core/src/errors/index.ts @@ -1,47 +1,3 @@ -import { HTTPError } from "./http" -import { UsageLimitError, FeatureDisabledError } from "./licensing" -import * as licensing from "./licensing" - -const codes = { - ...licensing.codes, -} - -const types = [licensing.type] - -const context = { - ...licensing.context, -} - -const getPublicError = (err: any) => { - let error - if (err.code || err.type) { - // add generic error information - error = { - code: err.code, - type: err.type, - } - - if (err.code && context[err.code]) { - error = { - ...error, - // get any additional context from this error - ...context[err.code](err), - } - } - } - - return error -} - -const pkg = { - codes, - types, - errors: { - UsageLimitError, - FeatureDisabledError, - HTTPError, - }, - getPublicError, -} - -export = pkg +export * from "./errors" +export { UsageLimitError, FeatureDisabledError } from "./licensing" +export { HTTPError } from "./http" diff --git a/packages/backend-core/src/events/events.ts b/packages/backend-core/src/events/events.ts index cda90d12c9..01928221a0 100644 --- a/packages/backend-core/src/events/events.ts +++ b/packages/backend-core/src/events/events.ts @@ -1,6 +1,6 @@ import { Event } from "@budibase/types" import { processors } from "./processors" -import * as identification from "./identification" +import identification from "./identification" import * as backfill from "./backfill" export const publishEvent = async ( diff --git a/packages/backend-core/src/events/identification.ts b/packages/backend-core/src/events/identification.ts index b93bd44968..8ac22b471c 100644 --- a/packages/backend-core/src/events/identification.ts +++ b/packages/backend-core/src/events/identification.ts @@ -33,7 +33,7 @@ const pkg = require("../../package.json") * - tenant * - installation */ -export const getCurrentIdentity = async (): Promise => { +const getCurrentIdentity = async (): Promise => { let identityContext = identityCtx.getIdentity() const environment = getDeploymentEnvironment() @@ -94,7 +94,7 @@ export const getCurrentIdentity = async (): Promise => { } } -export const identifyInstallationGroup = async ( +const identifyInstallationGroup = async ( installId: string, timestamp?: string | number ): Promise => { @@ -118,7 +118,7 @@ export const identifyInstallationGroup = async ( await identify({ ...group, id: `$${type}_${id}` }, timestamp) } -export const identifyTenantGroup = async ( +const identifyTenantGroup = async ( tenantId: string, account: Account | undefined, timestamp?: string | number @@ -156,7 +156,7 @@ export const identifyTenantGroup = async ( await identify({ ...group, id: `$${type}_${id}` }, timestamp) } -export const identifyUser = async ( +const identifyUser = async ( user: User, account: CloudAccount | undefined, timestamp?: string | number @@ -191,7 +191,7 @@ export const identifyUser = async ( await identify(identity, timestamp) } -export const identifyAccount = async (account: Account) => { +const identifyAccount = async (account: Account) => { let id = account.accountId const tenantId = account.tenantId let type = IdentityType.USER @@ -224,17 +224,11 @@ export const identifyAccount = async (account: Account) => { await identify(identity) } -export const identify = async ( - identity: Identity, - timestamp?: string | number -) => { +const identify = async (identity: Identity, timestamp?: string | number) => { await processors.identify(identity, timestamp) } -export const identifyGroup = async ( - group: Group, - timestamp?: string | number -) => { +const identifyGroup = async (group: Group, timestamp?: string | number) => { await processors.identifyGroup(group, timestamp) } @@ -250,7 +244,7 @@ const getHostingFromEnv = () => { return env.SELF_HOSTED ? Hosting.SELF : Hosting.CLOUD } -export const getInstallationId = async () => { +const getInstallationId = async () => { if (isAccountPortal()) { return "account-portal" } @@ -300,3 +294,14 @@ const formatDistinctId = (id: string, type: IdentityType) => { return id } } + +export default { + getCurrentIdentity, + identifyInstallationGroup, + identifyTenantGroup, + identifyUser, + identifyAccount, + identify, + identifyGroup, + getInstallationId, +} diff --git a/packages/backend-core/src/events/index.ts b/packages/backend-core/src/events/index.ts index f94c8b0267..d0d59a5b22 100644 --- a/packages/backend-core/src/events/index.ts +++ b/packages/backend-core/src/events/index.ts @@ -1,7 +1,7 @@ export * from "./publishers" export * as processors from "./processors" export * as analytics from "./analytics" -export * as identification from "./identification" +export { default as identification } from "./identification" export * as backfillCache from "./backfill" import { processors } from "./processors" diff --git a/packages/backend-core/src/events/processors/LoggingProcessor.ts b/packages/backend-core/src/events/processors/LoggingProcessor.ts index d41a82fbb4..6bb691a83a 100644 --- a/packages/backend-core/src/events/processors/LoggingProcessor.ts +++ b/packages/backend-core/src/events/processors/LoggingProcessor.ts @@ -23,7 +23,7 @@ export default class LoggingProcessor implements EventProcessor { return } let timestampString = getTimestampString(timestamp) - let message = `[audit] [tenant=${identity.tenantId}] [identityType=${identity.type}] [identity=${identity.id}] ${timestampString} ${event} ` + let message = `[audit] [identityType=${identity.type}] ${timestampString} ${event} ` if (env.isDev()) { message = message + `[debug: [properties=${JSON.stringify(properties)}] ]` } diff --git a/packages/backend-core/src/events/publishers/account.ts b/packages/backend-core/src/events/publishers/account.ts index 3f1a8a9161..d337e404ef 100644 --- a/packages/backend-core/src/events/publishers/account.ts +++ b/packages/backend-core/src/events/publishers/account.ts @@ -7,23 +7,29 @@ import { AccountVerifiedEvent, } from "@budibase/types" -export async function created(account: Account) { +async function created(account: Account) { const properties: AccountCreatedEvent = { tenantId: account.tenantId, } await publishEvent(Event.ACCOUNT_CREATED, properties) } -export async function deleted(account: Account) { +async function deleted(account: Account) { const properties: AccountDeletedEvent = { tenantId: account.tenantId, } await publishEvent(Event.ACCOUNT_DELETED, properties) } -export async function verified(account: Account) { +async function verified(account: Account) { const properties: AccountVerifiedEvent = { tenantId: account.tenantId, } await publishEvent(Event.ACCOUNT_VERIFIED, properties) } + +export default { + created, + deleted, + verified, +} diff --git a/packages/backend-core/src/events/publishers/app.ts b/packages/backend-core/src/events/publishers/app.ts index dd77b0b8a2..90da21f3f5 100644 --- a/packages/backend-core/src/events/publishers/app.ts +++ b/packages/backend-core/src/events/publishers/app.ts @@ -15,7 +15,7 @@ import { AppExportedEvent, } from "@budibase/types" -export const created = async (app: App, timestamp?: string | number) => { +const created = async (app: App, timestamp?: string | number) => { const properties: AppCreatedEvent = { appId: app.appId, version: app.version, @@ -23,7 +23,7 @@ export const created = async (app: App, timestamp?: string | number) => { await publishEvent(Event.APP_CREATED, properties, timestamp) } -export async function updated(app: App) { +async function updated(app: App) { const properties: AppUpdatedEvent = { appId: app.appId, version: app.version, @@ -31,35 +31,35 @@ export async function updated(app: App) { await publishEvent(Event.APP_UPDATED, properties) } -export async function deleted(app: App) { +async function deleted(app: App) { const properties: AppDeletedEvent = { appId: app.appId, } await publishEvent(Event.APP_DELETED, properties) } -export async function published(app: App, timestamp?: string | number) { +async function published(app: App, timestamp?: string | number) { const properties: AppPublishedEvent = { appId: app.appId, } await publishEvent(Event.APP_PUBLISHED, properties, timestamp) } -export async function unpublished(app: App) { +async function unpublished(app: App) { const properties: AppUnpublishedEvent = { appId: app.appId, } await publishEvent(Event.APP_UNPUBLISHED, properties) } -export async function fileImported(app: App) { +async function fileImported(app: App) { const properties: AppFileImportedEvent = { appId: app.appId, } await publishEvent(Event.APP_FILE_IMPORTED, properties) } -export async function templateImported(app: App, templateKey: string) { +async function templateImported(app: App, templateKey: string) { const properties: AppTemplateImportedEvent = { appId: app.appId, templateKey, @@ -67,7 +67,7 @@ export async function templateImported(app: App, templateKey: string) { await publishEvent(Event.APP_TEMPLATE_IMPORTED, properties) } -export async function versionUpdated( +async function versionUpdated( app: App, currentVersion: string, updatedToVersion: string @@ -80,7 +80,7 @@ export async function versionUpdated( await publishEvent(Event.APP_VERSION_UPDATED, properties) } -export async function versionReverted( +async function versionReverted( app: App, currentVersion: string, revertedToVersion: string @@ -93,16 +93,30 @@ export async function versionReverted( await publishEvent(Event.APP_VERSION_REVERTED, properties) } -export async function reverted(app: App) { +async function reverted(app: App) { const properties: AppRevertedEvent = { appId: app.appId, } await publishEvent(Event.APP_REVERTED, properties) } -export async function exported(app: App) { +async function exported(app: App) { const properties: AppExportedEvent = { appId: app.appId, } await publishEvent(Event.APP_EXPORTED, properties) } + +export default { + created, + updated, + deleted, + published, + unpublished, + fileImported, + templateImported, + versionUpdated, + versionReverted, + reverted, + exported, +} diff --git a/packages/backend-core/src/events/publishers/auth.ts b/packages/backend-core/src/events/publishers/auth.ts index 93378501f3..4436045599 100644 --- a/packages/backend-core/src/events/publishers/auth.ts +++ b/packages/backend-core/src/events/publishers/auth.ts @@ -12,7 +12,7 @@ import { } from "@budibase/types" import { identification } from ".." -export async function login(source: LoginSource) { +async function login(source: LoginSource) { const identity = await identification.getCurrentIdentity() const properties: LoginEvent = { userId: identity.id, @@ -21,7 +21,7 @@ export async function login(source: LoginSource) { await publishEvent(Event.AUTH_LOGIN, properties) } -export async function logout() { +async function logout() { const identity = await identification.getCurrentIdentity() const properties: LogoutEvent = { userId: identity.id, @@ -29,30 +29,39 @@ export async function logout() { await publishEvent(Event.AUTH_LOGOUT, properties) } -export async function SSOCreated(type: SSOType, timestamp?: string | number) { +async function SSOCreated(type: SSOType, timestamp?: string | number) { const properties: SSOCreatedEvent = { type, } await publishEvent(Event.AUTH_SSO_CREATED, properties, timestamp) } -export async function SSOUpdated(type: SSOType) { +async function SSOUpdated(type: SSOType) { const properties: SSOUpdatedEvent = { type, } await publishEvent(Event.AUTH_SSO_UPDATED, properties) } -export async function SSOActivated(type: SSOType, timestamp?: string | number) { +async function SSOActivated(type: SSOType, timestamp?: string | number) { const properties: SSOActivatedEvent = { type, } await publishEvent(Event.AUTH_SSO_ACTIVATED, properties, timestamp) } -export async function SSODeactivated(type: SSOType) { +async function SSODeactivated(type: SSOType) { const properties: SSODeactivatedEvent = { type, } await publishEvent(Event.AUTH_SSO_DEACTIVATED, properties) } + +export default { + login, + logout, + SSOCreated, + SSOUpdated, + SSOActivated, + SSODeactivated, +} diff --git a/packages/backend-core/src/events/publishers/automation.ts b/packages/backend-core/src/events/publishers/automation.ts index 8b2574b739..6eb36ab067 100644 --- a/packages/backend-core/src/events/publishers/automation.ts +++ b/packages/backend-core/src/events/publishers/automation.ts @@ -12,10 +12,7 @@ import { AutomationsRunEvent, } from "@budibase/types" -export async function created( - automation: Automation, - timestamp?: string | number -) { +async function created(automation: Automation, timestamp?: string | number) { const properties: AutomationCreatedEvent = { appId: automation.appId, automationId: automation._id as string, @@ -25,7 +22,7 @@ export async function created( await publishEvent(Event.AUTOMATION_CREATED, properties, timestamp) } -export async function triggerUpdated(automation: Automation) { +async function triggerUpdated(automation: Automation) { const properties: AutomationTriggerUpdatedEvent = { appId: automation.appId, automationId: automation._id as string, @@ -35,7 +32,7 @@ export async function triggerUpdated(automation: Automation) { await publishEvent(Event.AUTOMATION_TRIGGER_UPDATED, properties) } -export async function deleted(automation: Automation) { +async function deleted(automation: Automation) { const properties: AutomationDeletedEvent = { appId: automation.appId, automationId: automation._id as string, @@ -45,7 +42,7 @@ export async function deleted(automation: Automation) { await publishEvent(Event.AUTOMATION_DELETED, properties) } -export async function tested(automation: Automation) { +async function tested(automation: Automation) { const properties: AutomationTestedEvent = { appId: automation.appId, automationId: automation._id as string, @@ -55,14 +52,14 @@ export async function tested(automation: Automation) { await publishEvent(Event.AUTOMATION_TESTED, properties) } -export const run = async (count: number, timestamp?: string | number) => { +const run = async (count: number, timestamp?: string | number) => { const properties: AutomationsRunEvent = { count, } await publishEvent(Event.AUTOMATIONS_RUN, properties, timestamp) } -export async function stepCreated( +async function stepCreated( automation: Automation, step: AutomationStep, timestamp?: string | number @@ -78,10 +75,7 @@ export async function stepCreated( await publishEvent(Event.AUTOMATION_STEP_CREATED, properties, timestamp) } -export async function stepDeleted( - automation: Automation, - step: AutomationStep -) { +async function stepDeleted(automation: Automation, step: AutomationStep) { const properties: AutomationStepDeletedEvent = { appId: automation.appId, automationId: automation._id as string, @@ -92,3 +86,13 @@ export async function stepDeleted( } await publishEvent(Event.AUTOMATION_STEP_DELETED, properties) } + +export default { + created, + triggerUpdated, + deleted, + tested, + run, + stepCreated, + stepDeleted, +} diff --git a/packages/backend-core/src/events/publishers/backfill.ts b/packages/backend-core/src/events/publishers/backfill.ts index c16b3cc9dc..f2f6c7add8 100644 --- a/packages/backend-core/src/events/publishers/backfill.ts +++ b/packages/backend-core/src/events/publishers/backfill.ts @@ -8,18 +8,18 @@ import { InstallationBackfillSucceededEvent, InstallationBackfillFailedEvent, } from "@budibase/types" -const env = require("../../environment") +import env from "../../environment" const shouldSkip = !env.SELF_HOSTED && !env.isDev() -export async function appSucceeded(properties: AppBackfillSucceededEvent) { +async function appSucceeded(properties: AppBackfillSucceededEvent) { if (shouldSkip) { return } await publishEvent(Event.APP_BACKFILL_SUCCEEDED, properties) } -export async function appFailed(error: any) { +async function appFailed(error: any) { if (shouldSkip) { return } @@ -29,16 +29,14 @@ export async function appFailed(error: any) { await publishEvent(Event.APP_BACKFILL_FAILED, properties) } -export async function tenantSucceeded( - properties: TenantBackfillSucceededEvent -) { +async function tenantSucceeded(properties: TenantBackfillSucceededEvent) { if (shouldSkip) { return } await publishEvent(Event.TENANT_BACKFILL_SUCCEEDED, properties) } -export async function tenantFailed(error: any) { +async function tenantFailed(error: any) { if (shouldSkip) { return } @@ -48,7 +46,7 @@ export async function tenantFailed(error: any) { await publishEvent(Event.TENANT_BACKFILL_FAILED, properties) } -export async function installationSucceeded() { +async function installationSucceeded() { if (shouldSkip) { return } @@ -56,7 +54,7 @@ export async function installationSucceeded() { await publishEvent(Event.INSTALLATION_BACKFILL_SUCCEEDED, properties) } -export async function installationFailed(error: any) { +async function installationFailed(error: any) { if (shouldSkip) { return } @@ -65,3 +63,12 @@ export async function installationFailed(error: any) { } await publishEvent(Event.INSTALLATION_BACKFILL_FAILED, properties) } + +export default { + appSucceeded, + appFailed, + tenantSucceeded, + tenantFailed, + installationSucceeded, + installationFailed, +} diff --git a/packages/backend-core/src/events/publishers/backup.ts b/packages/backend-core/src/events/publishers/backup.ts index 4a68364016..12263fe1ff 100644 --- a/packages/backend-core/src/events/publishers/backup.ts +++ b/packages/backend-core/src/events/publishers/backup.ts @@ -8,7 +8,7 @@ import { } from "@budibase/types" import { publishEvent } from "../events" -export async function appBackupRestored(backup: AppBackup) { +async function appBackupRestored(backup: AppBackup) { const properties: AppBackupRestoreEvent = { appId: backup.appId, restoreId: backup._id!, @@ -18,7 +18,7 @@ export async function appBackupRestored(backup: AppBackup) { await publishEvent(Event.APP_BACKUP_RESTORED, properties) } -export async function appBackupTriggered( +async function appBackupTriggered( appId: string, backupId: string, type: AppBackupType, @@ -32,3 +32,8 @@ export async function appBackupTriggered( } await publishEvent(Event.APP_BACKUP_TRIGGERED, properties) } + +export default { + appBackupRestored, + appBackupTriggered, +} diff --git a/packages/backend-core/src/events/publishers/datasource.ts b/packages/backend-core/src/events/publishers/datasource.ts index d3ea7402f9..39a81ff1bc 100644 --- a/packages/backend-core/src/events/publishers/datasource.ts +++ b/packages/backend-core/src/events/publishers/datasource.ts @@ -14,10 +14,7 @@ function isCustom(datasource: Datasource) { return !sources.includes(datasource.source) } -export async function created( - datasource: Datasource, - timestamp?: string | number -) { +async function created(datasource: Datasource, timestamp?: string | number) { const properties: DatasourceCreatedEvent = { datasourceId: datasource._id as string, source: datasource.source, @@ -26,7 +23,7 @@ export async function created( await publishEvent(Event.DATASOURCE_CREATED, properties, timestamp) } -export async function updated(datasource: Datasource) { +async function updated(datasource: Datasource) { const properties: DatasourceUpdatedEvent = { datasourceId: datasource._id as string, source: datasource.source, @@ -35,7 +32,7 @@ export async function updated(datasource: Datasource) { await publishEvent(Event.DATASOURCE_UPDATED, properties) } -export async function deleted(datasource: Datasource) { +async function deleted(datasource: Datasource) { const properties: DatasourceDeletedEvent = { datasourceId: datasource._id as string, source: datasource.source, @@ -43,3 +40,9 @@ export async function deleted(datasource: Datasource) { } await publishEvent(Event.DATASOURCE_DELETED, properties) } + +export default { + created, + updated, + deleted, +} diff --git a/packages/backend-core/src/events/publishers/email.ts b/packages/backend-core/src/events/publishers/email.ts index 42c5fb4d4c..df9e41b39e 100644 --- a/packages/backend-core/src/events/publishers/email.ts +++ b/packages/backend-core/src/events/publishers/email.ts @@ -1,12 +1,17 @@ import { publishEvent } from "../events" import { Event, SMTPCreatedEvent, SMTPUpdatedEvent } from "@budibase/types" -export async function SMTPCreated(timestamp?: string | number) { +async function SMTPCreated(timestamp?: string | number) { const properties: SMTPCreatedEvent = {} await publishEvent(Event.EMAIL_SMTP_CREATED, properties, timestamp) } -export async function SMTPUpdated() { +async function SMTPUpdated() { const properties: SMTPUpdatedEvent = {} await publishEvent(Event.EMAIL_SMTP_UPDATED, properties) } + +export default { + SMTPCreated, + SMTPUpdated, +} diff --git a/packages/backend-core/src/events/publishers/environmentVariable.ts b/packages/backend-core/src/events/publishers/environmentVariable.ts new file mode 100644 index 0000000000..d28e259b82 --- /dev/null +++ b/packages/backend-core/src/events/publishers/environmentVariable.ts @@ -0,0 +1,38 @@ +import { + Event, + EnvironmentVariableCreatedEvent, + EnvironmentVariableDeletedEvent, + EnvironmentVariableUpgradePanelOpenedEvent, +} from "@budibase/types" +import { publishEvent } from "../events" + +async function created(name: string, environments: string[]) { + const properties: EnvironmentVariableCreatedEvent = { + name, + environments, + } + await publishEvent(Event.ENVIRONMENT_VARIABLE_CREATED, properties) +} + +async function deleted(name: string) { + const properties: EnvironmentVariableDeletedEvent = { + name, + } + await publishEvent(Event.ENVIRONMENT_VARIABLE_DELETED, properties) +} + +async function upgradePanelOpened(userId: string) { + const properties: EnvironmentVariableUpgradePanelOpenedEvent = { + userId, + } + await publishEvent( + Event.ENVIRONMENT_VARIABLE_UPGRADE_PANEL_OPENED, + properties + ) +} + +export default { + created, + deleted, + upgradePanelOpened, +} diff --git a/packages/backend-core/src/events/publishers/group.ts b/packages/backend-core/src/events/publishers/group.ts index b4fd0d1469..d79920562b 100644 --- a/packages/backend-core/src/events/publishers/group.ts +++ b/packages/backend-core/src/events/publishers/group.ts @@ -11,28 +11,28 @@ import { UserGroupRoles, } from "@budibase/types" -export async function created(group: UserGroup, timestamp?: number) { +async function created(group: UserGroup, timestamp?: number) { const properties: GroupCreatedEvent = { groupId: group._id as string, } await publishEvent(Event.USER_GROUP_CREATED, properties, timestamp) } -export async function updated(group: UserGroup) { +async function updated(group: UserGroup) { const properties: GroupUpdatedEvent = { groupId: group._id as string, } await publishEvent(Event.USER_GROUP_UPDATED, properties) } -export async function deleted(group: UserGroup) { +async function deleted(group: UserGroup) { const properties: GroupDeletedEvent = { groupId: group._id as string, } await publishEvent(Event.USER_GROUP_DELETED, properties) } -export async function usersAdded(count: number, group: UserGroup) { +async function usersAdded(count: number, group: UserGroup) { const properties: GroupUsersAddedEvent = { count, groupId: group._id as string, @@ -40,7 +40,7 @@ export async function usersAdded(count: number, group: UserGroup) { await publishEvent(Event.USER_GROUP_USERS_ADDED, properties) } -export async function usersDeleted(count: number, group: UserGroup) { +async function usersDeleted(count: number, group: UserGroup) { const properties: GroupUsersDeletedEvent = { count, groupId: group._id as string, @@ -48,7 +48,7 @@ export async function usersDeleted(count: number, group: UserGroup) { await publishEvent(Event.USER_GROUP_USERS_REMOVED, properties) } -export async function createdOnboarding(groupId: string) { +async function createdOnboarding(groupId: string) { const properties: GroupAddedOnboardingEvent = { groupId: groupId, onboarding: true, @@ -56,9 +56,19 @@ export async function createdOnboarding(groupId: string) { await publishEvent(Event.USER_GROUP_ONBOARDING, properties) } -export async function permissionsEdited(roles: UserGroupRoles) { +async function permissionsEdited(roles: UserGroupRoles) { const properties: UserGroupRoles = { ...roles, } await publishEvent(Event.USER_GROUP_PERMISSIONS_EDITED, properties) } + +export default { + created, + updated, + deleted, + usersAdded, + usersDeleted, + createdOnboarding, + permissionsEdited, +} diff --git a/packages/backend-core/src/events/publishers/index.ts b/packages/backend-core/src/events/publishers/index.ts index 7306312a8f..34e47b2990 100644 --- a/packages/backend-core/src/events/publishers/index.ts +++ b/packages/backend-core/src/events/publishers/index.ts @@ -1,22 +1,23 @@ -export * as account from "./account" -export * as app from "./app" -export * as auth from "./auth" -export * as automation from "./automation" -export * as datasource from "./datasource" -export * as email from "./email" -export * as license from "./license" -export * as layout from "./layout" -export * as org from "./org" -export * as query from "./query" -export * as role from "./role" -export * as screen from "./screen" -export * as rows from "./rows" -export * as table from "./table" -export * as serve from "./serve" -export * as user from "./user" -export * as view from "./view" -export * as installation from "./installation" -export * as backfill from "./backfill" -export * as group from "./group" -export * as plugin from "./plugin" -export * as backup from "./backup" +export { default as account } from "./account" +export { default as app } from "./app" +export { default as auth } from "./auth" +export { default as automation } from "./automation" +export { default as datasource } from "./datasource" +export { default as email } from "./email" +export { default as license } from "./license" +export { default as layout } from "./layout" +export { default as org } from "./org" +export { default as query } from "./query" +export { default as role } from "./role" +export { default as screen } from "./screen" +export { default as rows } from "./rows" +export { default as table } from "./table" +export { default as serve } from "./serve" +export { default as user } from "./user" +export { default as view } from "./view" +export { default as installation } from "./installation" +export { default as backfill } from "./backfill" +export { default as group } from "./group" +export { default as plugin } from "./plugin" +export { default as backup } from "./backup" +export { default as environmentVariable } from "./environmentVariable" diff --git a/packages/backend-core/src/events/publishers/installation.ts b/packages/backend-core/src/events/publishers/installation.ts index ef27935210..f1ca75a0dd 100644 --- a/packages/backend-core/src/events/publishers/installation.ts +++ b/packages/backend-core/src/events/publishers/installation.ts @@ -1,14 +1,14 @@ import { publishEvent } from "../events" import { Event, VersionCheckedEvent, VersionChangeEvent } from "@budibase/types" -export async function versionChecked(version: string) { +async function versionChecked(version: string) { const properties: VersionCheckedEvent = { currentVersion: version, } await publishEvent(Event.INSTALLATION_VERSION_CHECKED, properties) } -export async function upgraded(from: string, to: string) { +async function upgraded(from: string, to: string) { const properties: VersionChangeEvent = { from, to, @@ -17,7 +17,7 @@ export async function upgraded(from: string, to: string) { await publishEvent(Event.INSTALLATION_VERSION_UPGRADED, properties) } -export async function downgraded(from: string, to: string) { +async function downgraded(from: string, to: string) { const properties: VersionChangeEvent = { from, to, @@ -25,7 +25,14 @@ export async function downgraded(from: string, to: string) { await publishEvent(Event.INSTALLATION_VERSION_DOWNGRADED, properties) } -export async function firstStartup() { +async function firstStartup() { const properties = {} await publishEvent(Event.INSTALLATION_FIRST_STARTUP, properties) } + +export default { + versionChecked, + upgraded, + downgraded, + firstStartup, +} diff --git a/packages/backend-core/src/events/publishers/layout.ts b/packages/backend-core/src/events/publishers/layout.ts index 1eede40143..6abb226049 100644 --- a/packages/backend-core/src/events/publishers/layout.ts +++ b/packages/backend-core/src/events/publishers/layout.ts @@ -6,16 +6,21 @@ import { LayoutDeletedEvent, } from "@budibase/types" -export async function created(layout: Layout, timestamp?: string | number) { +async function created(layout: Layout, timestamp?: string | number) { const properties: LayoutCreatedEvent = { layoutId: layout._id as string, } await publishEvent(Event.LAYOUT_CREATED, properties, timestamp) } -export async function deleted(layoutId: string) { +async function deleted(layoutId: string) { const properties: LayoutDeletedEvent = { layoutId, } await publishEvent(Event.LAYOUT_DELETED, properties) } + +export default { + created, + deleted, +} diff --git a/packages/backend-core/src/events/publishers/license.ts b/packages/backend-core/src/events/publishers/license.ts index 84472e408f..aff3286c87 100644 --- a/packages/backend-core/src/events/publishers/license.ts +++ b/packages/backend-core/src/events/publishers/license.ts @@ -13,7 +13,7 @@ import { LicensePaymentRecoveredEvent, } from "@budibase/types" -export async function tierChanged(account: Account, from: number, to: number) { +async function tierChanged(account: Account, from: number, to: number) { const properties: LicenseTierChangedEvent = { accountId: account.accountId, to, @@ -22,11 +22,7 @@ export async function tierChanged(account: Account, from: number, to: number) { await publishEvent(Event.LICENSE_TIER_CHANGED, properties) } -export async function planChanged( - account: Account, - from: PlanType, - to: PlanType -) { +async function planChanged(account: Account, from: PlanType, to: PlanType) { const properties: LicensePlanChangedEvent = { accountId: account.accountId, to, @@ -35,44 +31,55 @@ export async function planChanged( await publishEvent(Event.LICENSE_PLAN_CHANGED, properties) } -export async function activated(account: Account) { +async function activated(account: Account) { const properties: LicenseActivatedEvent = { accountId: account.accountId, } await publishEvent(Event.LICENSE_ACTIVATED, properties) } -export async function checkoutOpened(account: Account) { +async function checkoutOpened(account: Account) { const properties: LicenseCheckoutOpenedEvent = { accountId: account.accountId, } await publishEvent(Event.LICENSE_CHECKOUT_OPENED, properties) } -export async function checkoutSuccess(account: Account) { +async function checkoutSuccess(account: Account) { const properties: LicenseCheckoutSuccessEvent = { accountId: account.accountId, } await publishEvent(Event.LICENSE_CHECKOUT_SUCCESS, properties) } -export async function portalOpened(account: Account) { +async function portalOpened(account: Account) { const properties: LicensePortalOpenedEvent = { accountId: account.accountId, } await publishEvent(Event.LICENSE_PORTAL_OPENED, properties) } -export async function paymentFailed(account: Account) { +async function paymentFailed(account: Account) { const properties: LicensePaymentFailedEvent = { accountId: account.accountId, } await publishEvent(Event.LICENSE_PAYMENT_FAILED, properties) } -export async function paymentRecovered(account: Account) { +async function paymentRecovered(account: Account) { const properties: LicensePaymentRecoveredEvent = { accountId: account.accountId, } await publishEvent(Event.LICENSE_PAYMENT_RECOVERED, properties) } + +export default { + tierChanged, + planChanged, + activated, + checkoutOpened, + checkoutSuccess, + portalOpened, + paymentFailed, + paymentRecovered, +} diff --git a/packages/backend-core/src/events/publishers/org.ts b/packages/backend-core/src/events/publishers/org.ts index 4567357db8..684bb68dac 100644 --- a/packages/backend-core/src/events/publishers/org.ts +++ b/packages/backend-core/src/events/publishers/org.ts @@ -1,29 +1,37 @@ import { publishEvent } from "../events" import { Event } from "@budibase/types" -export async function nameUpdated(timestamp?: string | number) { +async function nameUpdated(timestamp?: string | number) { const properties = {} await publishEvent(Event.ORG_NAME_UPDATED, properties, timestamp) } -export async function logoUpdated(timestamp?: string | number) { +async function logoUpdated(timestamp?: string | number) { const properties = {} await publishEvent(Event.ORG_LOGO_UPDATED, properties, timestamp) } -export async function platformURLUpdated(timestamp?: string | number) { +async function platformURLUpdated(timestamp?: string | number) { const properties = {} await publishEvent(Event.ORG_PLATFORM_URL_UPDATED, properties, timestamp) } // TODO -export async function analyticsOptOut() { +async function analyticsOptOut() { const properties = {} await publishEvent(Event.ANALYTICS_OPT_OUT, properties) } -export async function analyticsOptIn() { +async function analyticsOptIn() { const properties = {} await publishEvent(Event.ANALYTICS_OPT_OUT, properties) } + +export default { + nameUpdated, + logoUpdated, + platformURLUpdated, + analyticsOptOut, + analyticsOptIn, +} diff --git a/packages/backend-core/src/events/publishers/plugin.ts b/packages/backend-core/src/events/publishers/plugin.ts index 4e4d87cf56..b5a686f95d 100644 --- a/packages/backend-core/src/events/publishers/plugin.ts +++ b/packages/backend-core/src/events/publishers/plugin.ts @@ -7,7 +7,7 @@ import { PluginInitEvent, } from "@budibase/types" -export async function init(plugin: Plugin) { +async function init(plugin: Plugin) { const properties: PluginInitEvent = { type: plugin.schema.type, name: plugin.name, @@ -17,7 +17,7 @@ export async function init(plugin: Plugin) { await publishEvent(Event.PLUGIN_INIT, properties) } -export async function imported(plugin: Plugin) { +async function imported(plugin: Plugin) { const properties: PluginImportedEvent = { pluginId: plugin._id as string, type: plugin.schema.type, @@ -29,7 +29,7 @@ export async function imported(plugin: Plugin) { await publishEvent(Event.PLUGIN_IMPORTED, properties) } -export async function deleted(plugin: Plugin) { +async function deleted(plugin: Plugin) { const properties: PluginDeletedEvent = { pluginId: plugin._id as string, type: plugin.schema.type, @@ -39,3 +39,9 @@ export async function deleted(plugin: Plugin) { } await publishEvent(Event.PLUGIN_DELETED, properties) } + +export default { + init, + imported, + deleted, +} diff --git a/packages/backend-core/src/events/publishers/query.ts b/packages/backend-core/src/events/publishers/query.ts index 1bcf561fd0..7d28129cf6 100644 --- a/packages/backend-core/src/events/publishers/query.ts +++ b/packages/backend-core/src/events/publishers/query.ts @@ -13,7 +13,7 @@ import { /* eslint-disable */ -export const created = async ( +const created = async ( datasource: Datasource, query: Query, timestamp?: string | number @@ -27,7 +27,7 @@ export const created = async ( await publishEvent(Event.QUERY_CREATED, properties, timestamp) } -export const updated = async (datasource: Datasource, query: Query) => { +const updated = async (datasource: Datasource, query: Query) => { const properties: QueryUpdatedEvent = { queryId: query._id as string, datasourceId: datasource._id as string, @@ -37,7 +37,7 @@ export const updated = async (datasource: Datasource, query: Query) => { await publishEvent(Event.QUERY_UPDATED, properties) } -export const deleted = async (datasource: Datasource, query: Query) => { +const deleted = async (datasource: Datasource, query: Query) => { const properties: QueryDeletedEvent = { queryId: query._id as string, datasourceId: datasource._id as string, @@ -47,7 +47,7 @@ export const deleted = async (datasource: Datasource, query: Query) => { await publishEvent(Event.QUERY_DELETED, properties) } -export const imported = async ( +const imported = async ( datasource: Datasource, importSource: any, count: any @@ -61,14 +61,14 @@ export const imported = async ( await publishEvent(Event.QUERY_IMPORT, properties) } -export const run = async (count: number, timestamp?: string | number) => { +const run = async (count: number, timestamp?: string | number) => { const properties: QueriesRunEvent = { count, } await publishEvent(Event.QUERIES_RUN, properties, timestamp) } -export const previewed = async (datasource: Datasource, query: Query) => { +const previewed = async (datasource: Datasource, query: Query) => { const properties: QueryPreviewedEvent = { queryId: query._id, datasourceId: datasource._id as string, @@ -77,3 +77,12 @@ export const previewed = async (datasource: Datasource, query: Query) => { } await publishEvent(Event.QUERY_PREVIEWED, properties) } + +export default { + created, + updated, + deleted, + imported, + run, + previewed, +} diff --git a/packages/backend-core/src/events/publishers/role.ts b/packages/backend-core/src/events/publishers/role.ts index 99074d76a5..2fbdc8b76b 100644 --- a/packages/backend-core/src/events/publishers/role.ts +++ b/packages/backend-core/src/events/publishers/role.ts @@ -10,7 +10,7 @@ import { User, } from "@budibase/types" -export async function created(role: Role, timestamp?: string | number) { +async function created(role: Role, timestamp?: string | number) { const properties: RoleCreatedEvent = { roleId: role._id as string, permissionId: role.permissionId, @@ -19,7 +19,7 @@ export async function created(role: Role, timestamp?: string | number) { await publishEvent(Event.ROLE_CREATED, properties, timestamp) } -export async function updated(role: Role) { +async function updated(role: Role) { const properties: RoleUpdatedEvent = { roleId: role._id as string, permissionId: role.permissionId, @@ -28,7 +28,7 @@ export async function updated(role: Role) { await publishEvent(Event.ROLE_UPDATED, properties) } -export async function deleted(role: Role) { +async function deleted(role: Role) { const properties: RoleDeletedEvent = { roleId: role._id as string, permissionId: role.permissionId, @@ -37,7 +37,7 @@ export async function deleted(role: Role) { await publishEvent(Event.ROLE_DELETED, properties) } -export async function assigned(user: User, roleId: string, timestamp?: number) { +async function assigned(user: User, roleId: string, timestamp?: number) { const properties: RoleAssignedEvent = { userId: user._id as string, roleId, @@ -45,10 +45,18 @@ export async function assigned(user: User, roleId: string, timestamp?: number) { await publishEvent(Event.ROLE_ASSIGNED, properties, timestamp) } -export async function unassigned(user: User, roleId: string) { +async function unassigned(user: User, roleId: string) { const properties: RoleUnassignedEvent = { userId: user._id as string, roleId, } await publishEvent(Event.ROLE_UNASSIGNED, properties) } + +export default { + created, + updated, + deleted, + assigned, + unassigned, +} diff --git a/packages/backend-core/src/events/publishers/rows.ts b/packages/backend-core/src/events/publishers/rows.ts index 487e7ea074..9608613e89 100644 --- a/packages/backend-core/src/events/publishers/rows.ts +++ b/packages/backend-core/src/events/publishers/rows.ts @@ -3,28 +3,27 @@ import { Event, RowsImportedEvent, RowsCreatedEvent, - RowImportFormat, Table, } from "@budibase/types" /* eslint-disable */ -export const created = async (count: number, timestamp?: string | number) => { +const created = async (count: number, timestamp?: string | number) => { const properties: RowsCreatedEvent = { count, } await publishEvent(Event.ROWS_CREATED, properties, timestamp) } -export const imported = async ( - table: Table, - format: RowImportFormat, - count: number -) => { +const imported = async (table: Table, count: number) => { const properties: RowsImportedEvent = { tableId: table._id as string, - format, count, } await publishEvent(Event.ROWS_IMPORTED, properties) } + +export default { + created, + imported, +} diff --git a/packages/backend-core/src/events/publishers/screen.ts b/packages/backend-core/src/events/publishers/screen.ts index 966bf72e52..27264b5847 100644 --- a/packages/backend-core/src/events/publishers/screen.ts +++ b/packages/backend-core/src/events/publishers/screen.ts @@ -6,7 +6,7 @@ import { ScreenDeletedEvent, } from "@budibase/types" -export async function created(screen: Screen, timestamp?: string | number) { +async function created(screen: Screen, timestamp?: string | number) { const properties: ScreenCreatedEvent = { layoutId: screen.layoutId, screenId: screen._id as string, @@ -15,7 +15,7 @@ export async function created(screen: Screen, timestamp?: string | number) { await publishEvent(Event.SCREEN_CREATED, properties, timestamp) } -export async function deleted(screen: Screen) { +async function deleted(screen: Screen) { const properties: ScreenDeletedEvent = { layoutId: screen.layoutId, screenId: screen._id as string, @@ -23,3 +23,8 @@ export async function deleted(screen: Screen) { } await publishEvent(Event.SCREEN_DELETED, properties) } + +export default { + created, + deleted, +} diff --git a/packages/backend-core/src/events/publishers/serve.ts b/packages/backend-core/src/events/publishers/serve.ts index 128e0b9b11..64e24e20a7 100644 --- a/packages/backend-core/src/events/publishers/serve.ts +++ b/packages/backend-core/src/events/publishers/serve.ts @@ -7,14 +7,14 @@ import { AppServedEvent, } from "@budibase/types" -export async function servedBuilder(timezone: string) { +async function servedBuilder(timezone: string) { const properties: BuilderServedEvent = { timezone, } await publishEvent(Event.SERVED_BUILDER, properties) } -export async function servedApp(app: App, timezone: string) { +async function servedApp(app: App, timezone: string) { const properties: AppServedEvent = { appVersion: app.version, timezone, @@ -22,7 +22,7 @@ export async function servedApp(app: App, timezone: string) { await publishEvent(Event.SERVED_APP, properties) } -export async function servedAppPreview(app: App, timezone: string) { +async function servedAppPreview(app: App, timezone: string) { const properties: AppPreviewServedEvent = { appId: app.appId, appVersion: app.version, @@ -30,3 +30,9 @@ export async function servedAppPreview(app: App, timezone: string) { } await publishEvent(Event.SERVED_APP_PREVIEW, properties) } + +export default { + servedBuilder, + servedApp, + servedAppPreview, +} diff --git a/packages/backend-core/src/events/publishers/table.ts b/packages/backend-core/src/events/publishers/table.ts index ba53163ca3..d50f4df0e1 100644 --- a/packages/backend-core/src/events/publishers/table.ts +++ b/packages/backend-core/src/events/publishers/table.ts @@ -2,7 +2,6 @@ import { publishEvent } from "../events" import { Event, TableExportFormat, - TableImportFormat, Table, TableCreatedEvent, TableUpdatedEvent, @@ -11,28 +10,28 @@ import { TableImportedEvent, } from "@budibase/types" -export async function created(table: Table, timestamp?: string | number) { +async function created(table: Table, timestamp?: string | number) { const properties: TableCreatedEvent = { tableId: table._id as string, } await publishEvent(Event.TABLE_CREATED, properties, timestamp) } -export async function updated(table: Table) { +async function updated(table: Table) { const properties: TableUpdatedEvent = { tableId: table._id as string, } await publishEvent(Event.TABLE_UPDATED, properties) } -export async function deleted(table: Table) { +async function deleted(table: Table) { const properties: TableDeletedEvent = { tableId: table._id as string, } await publishEvent(Event.TABLE_DELETED, properties) } -export async function exported(table: Table, format: TableExportFormat) { +async function exported(table: Table, format: TableExportFormat) { const properties: TableExportedEvent = { tableId: table._id as string, format, @@ -40,10 +39,17 @@ export async function exported(table: Table, format: TableExportFormat) { await publishEvent(Event.TABLE_EXPORTED, properties) } -export async function imported(table: Table, format: TableImportFormat) { +async function imported(table: Table) { const properties: TableImportedEvent = { tableId: table._id as string, - format, } await publishEvent(Event.TABLE_IMPORTED, properties) } + +export default { + created, + updated, + deleted, + exported, + imported, +} diff --git a/packages/backend-core/src/events/publishers/user.ts b/packages/backend-core/src/events/publishers/user.ts index 2c83b267d6..1fe50149b5 100644 --- a/packages/backend-core/src/events/publishers/user.ts +++ b/packages/backend-core/src/events/publishers/user.ts @@ -13,32 +13,40 @@ import { UserPermissionAssignedEvent, UserPermissionRemovedEvent, UserUpdatedEvent, + UserOnboardingEvent, } from "@budibase/types" -export async function created(user: User, timestamp?: number) { +async function created(user: User, timestamp?: number) { const properties: UserCreatedEvent = { userId: user._id as string, } await publishEvent(Event.USER_CREATED, properties, timestamp) } -export async function updated(user: User) { +async function updated(user: User) { const properties: UserUpdatedEvent = { userId: user._id as string, } await publishEvent(Event.USER_UPDATED, properties) } -export async function deleted(user: User) { +async function deleted(user: User) { const properties: UserDeletedEvent = { userId: user._id as string, } await publishEvent(Event.USER_DELETED, properties) } +export async function onboardingComplete(user: User) { + const properties: UserOnboardingEvent = { + userId: user._id as string, + } + await publishEvent(Event.USER_ONBOARDING_COMPLETE, properties) +} + // PERMISSIONS -export async function permissionAdminAssigned(user: User, timestamp?: number) { +async function permissionAdminAssigned(user: User, timestamp?: number) { const properties: UserPermissionAssignedEvent = { userId: user._id as string, } @@ -49,17 +57,14 @@ export async function permissionAdminAssigned(user: User, timestamp?: number) { ) } -export async function permissionAdminRemoved(user: User) { +async function permissionAdminRemoved(user: User) { const properties: UserPermissionRemovedEvent = { userId: user._id as string, } await publishEvent(Event.USER_PERMISSION_ADMIN_REMOVED, properties) } -export async function permissionBuilderAssigned( - user: User, - timestamp?: number -) { +async function permissionBuilderAssigned(user: User, timestamp?: number) { const properties: UserPermissionAssignedEvent = { userId: user._id as string, } @@ -70,7 +75,7 @@ export async function permissionBuilderAssigned( ) } -export async function permissionBuilderRemoved(user: User) { +async function permissionBuilderRemoved(user: User) { const properties: UserPermissionRemovedEvent = { userId: user._id as string, } @@ -79,12 +84,12 @@ export async function permissionBuilderRemoved(user: User) { // INVITE -export async function invited() { +async function invited() { const properties: UserInvitedEvent = {} await publishEvent(Event.USER_INVITED, properties) } -export async function inviteAccepted(user: User) { +async function inviteAccepted(user: User) { const properties: UserInviteAcceptedEvent = { userId: user._id as string, } @@ -93,30 +98,47 @@ export async function inviteAccepted(user: User) { // PASSWORD -export async function passwordForceReset(user: User) { +async function passwordForceReset(user: User) { const properties: UserPasswordForceResetEvent = { userId: user._id as string, } await publishEvent(Event.USER_PASSWORD_FORCE_RESET, properties) } -export async function passwordUpdated(user: User) { +async function passwordUpdated(user: User) { const properties: UserPasswordUpdatedEvent = { userId: user._id as string, } await publishEvent(Event.USER_PASSWORD_UPDATED, properties) } -export async function passwordResetRequested(user: User) { +async function passwordResetRequested(user: User) { const properties: UserPasswordResetRequestedEvent = { userId: user._id as string, } await publishEvent(Event.USER_PASSWORD_RESET_REQUESTED, properties) } -export async function passwordReset(user: User) { +async function passwordReset(user: User) { const properties: UserPasswordResetEvent = { userId: user._id as string, } await publishEvent(Event.USER_PASSWORD_RESET, properties) } + +export default { + created, + updated, + deleted, + permissionAdminAssigned, + permissionAdminRemoved, + permissionBuilderAssigned, + permissionBuilderRemoved, + onboardingComplete, + invited, + inviteAccepted, + passwordForceReset, + passwordUpdated, + passwordResetRequested, + passwordReset, +} diff --git a/packages/backend-core/src/events/publishers/view.ts b/packages/backend-core/src/events/publishers/view.ts index 17947758d5..ccbf960b04 100644 --- a/packages/backend-core/src/events/publishers/view.ts +++ b/packages/backend-core/src/events/publishers/view.ts @@ -19,28 +19,28 @@ import { /* eslint-disable */ -export async function created(view: View, timestamp?: string | number) { +async function created(view: View, timestamp?: string | number) { const properties: ViewCreatedEvent = { tableId: view.tableId, } await publishEvent(Event.VIEW_CREATED, properties, timestamp) } -export async function updated(view: View) { +async function updated(view: View) { const properties: ViewUpdatedEvent = { tableId: view.tableId, } await publishEvent(Event.VIEW_UPDATED, properties) } -export async function deleted(view: View) { +async function deleted(view: View) { const properties: ViewDeletedEvent = { tableId: view.tableId, } await publishEvent(Event.VIEW_DELETED, properties) } -export async function exported(table: Table, format: TableExportFormat) { +async function exported(table: Table, format: TableExportFormat) { const properties: ViewExportedEvent = { tableId: table._id as string, format, @@ -48,31 +48,28 @@ export async function exported(table: Table, format: TableExportFormat) { await publishEvent(Event.VIEW_EXPORTED, properties) } -export async function filterCreated(view: View, timestamp?: string | number) { +async function filterCreated(view: View, timestamp?: string | number) { const properties: ViewFilterCreatedEvent = { tableId: view.tableId, } await publishEvent(Event.VIEW_FILTER_CREATED, properties, timestamp) } -export async function filterUpdated(view: View) { +async function filterUpdated(view: View) { const properties: ViewFilterUpdatedEvent = { tableId: view.tableId, } await publishEvent(Event.VIEW_FILTER_UPDATED, properties) } -export async function filterDeleted(view: View) { +async function filterDeleted(view: View) { const properties: ViewFilterDeletedEvent = { tableId: view.tableId, } await publishEvent(Event.VIEW_FILTER_DELETED, properties) } -export async function calculationCreated( - view: View, - timestamp?: string | number -) { +async function calculationCreated(view: View, timestamp?: string | number) { const properties: ViewCalculationCreatedEvent = { tableId: view.tableId, calculation: view.calculation as ViewCalculation, @@ -80,7 +77,7 @@ export async function calculationCreated( await publishEvent(Event.VIEW_CALCULATION_CREATED, properties, timestamp) } -export async function calculationUpdated(view: View) { +async function calculationUpdated(view: View) { const properties: ViewCalculationUpdatedEvent = { tableId: view.tableId, calculation: view.calculation as ViewCalculation, @@ -88,10 +85,23 @@ export async function calculationUpdated(view: View) { await publishEvent(Event.VIEW_CALCULATION_UPDATED, properties) } -export async function calculationDeleted(existingView: View) { +async function calculationDeleted(existingView: View) { const properties: ViewCalculationDeletedEvent = { tableId: existingView.tableId, calculation: existingView.calculation as ViewCalculation, } await publishEvent(Event.VIEW_CALCULATION_DELETED, properties) } + +export default { + created, + updated, + deleted, + exported, + filterCreated, + filterUpdated, + filterDeleted, + calculationCreated, + calculationUpdated, + calculationDeleted, +} diff --git a/packages/backend-core/src/featureFlags/index.ts b/packages/backend-core/src/featureFlags/index.ts index 71e226c976..34ee3599a5 100644 --- a/packages/backend-core/src/featureFlags/index.ts +++ b/packages/backend-core/src/featureFlags/index.ts @@ -6,7 +6,7 @@ import * as tenancy from "../tenancy" * The env var is formatted as: * tenant1:feature1:feature2,tenant2:feature1 */ -function getFeatureFlags() { +export function buildFeatureFlags() { if (!env.TENANT_FEATURE_FLAGS) { return } @@ -27,8 +27,6 @@ function getFeatureFlags() { return tenantFeatureFlags } -const TENANT_FEATURE_FLAGS = getFeatureFlags() - export function isEnabled(featureFlag: string) { const tenantId = tenancy.getTenantId() const flags = getTenantFeatureFlags(tenantId) @@ -36,18 +34,36 @@ export function isEnabled(featureFlag: string) { } export function getTenantFeatureFlags(tenantId: string) { - const flags = [] + let flags: string[] = [] + const envFlags = buildFeatureFlags() + if (envFlags) { + const globalFlags = envFlags["*"] + const tenantFlags = envFlags[tenantId] || [] - if (TENANT_FEATURE_FLAGS) { - const globalFlags = TENANT_FEATURE_FLAGS["*"] - const tenantFlags = TENANT_FEATURE_FLAGS[tenantId] + // Explicitly exclude tenants from global features if required. + // Prefix the tenant flag with '!' + const tenantOverrides = tenantFlags.reduce( + (acc: string[], flag: string) => { + if (flag.startsWith("!")) { + let stripped = flag.substring(1) + acc.push(stripped) + } + return acc + }, + [] + ) if (globalFlags) { flags.push(...globalFlags) } - if (tenantFlags) { + if (tenantFlags.length) { flags.push(...tenantFlags) } + + // Purge any tenant specific overrides + flags = flags.filter(flag => { + return tenantOverrides.indexOf(flag) == -1 && !flag.startsWith("!") + }) } return flags @@ -57,4 +73,5 @@ export enum TenantFeatureFlag { LICENSING = "LICENSING", GOOGLE_SHEETS = "GOOGLE_SHEETS", USER_GROUPS = "USER_GROUPS", + ONBOARDING_TOUR = "ONBOARDING_TOUR", } diff --git a/packages/backend-core/src/featureFlags/tests/featureFlags.spec.ts b/packages/backend-core/src/featureFlags/tests/featureFlags.spec.ts new file mode 100644 index 0000000000..1b68959329 --- /dev/null +++ b/packages/backend-core/src/featureFlags/tests/featureFlags.spec.ts @@ -0,0 +1,85 @@ +import { + TenantFeatureFlag, + buildFeatureFlags, + getTenantFeatureFlags, +} from "../" +import env from "../../environment" + +const { ONBOARDING_TOUR, LICENSING, USER_GROUPS } = TenantFeatureFlag + +describe("featureFlags", () => { + beforeEach(() => { + env._set("TENANT_FEATURE_FLAGS", "") + }) + + it("Should return no flags when the TENANT_FEATURE_FLAG is empty", async () => { + let features = buildFeatureFlags() + expect(features).toBeUndefined() + }) + + it("Should generate a map of global and named tenant feature flags from the env value", async () => { + env._set( + "TENANT_FEATURE_FLAGS", + `*:${ONBOARDING_TOUR},tenant1:!${ONBOARDING_TOUR},tenant2:${USER_GROUPS},tenant1:${LICENSING}` + ) + + const parsedFlags: Record = { + "*": [ONBOARDING_TOUR], + tenant1: [`!${ONBOARDING_TOUR}`, LICENSING], + tenant2: [USER_GROUPS], + } + + let features = buildFeatureFlags() + + expect(features).toBeDefined() + expect(features).toEqual(parsedFlags) + }) + + it("Should add feature flag flag only to explicitly configured tenant", async () => { + env._set( + "TENANT_FEATURE_FLAGS", + `*:${LICENSING},*:${USER_GROUPS},tenant1:${ONBOARDING_TOUR}` + ) + + let tenant1Flags = getTenantFeatureFlags("tenant1") + let tenant2Flags = getTenantFeatureFlags("tenant2") + + expect(tenant1Flags).toBeDefined() + expect(tenant1Flags).toEqual([LICENSING, USER_GROUPS, ONBOARDING_TOUR]) + + expect(tenant2Flags).toBeDefined() + expect(tenant2Flags).toEqual([LICENSING, USER_GROUPS]) + }) +}) + +it("Should exclude tenant1 from global feature flag", async () => { + env._set( + "TENANT_FEATURE_FLAGS", + `*:${LICENSING},*:${ONBOARDING_TOUR},tenant1:!${ONBOARDING_TOUR}` + ) + + let tenant1Flags = getTenantFeatureFlags("tenant1") + let tenant2Flags = getTenantFeatureFlags("tenant2") + + expect(tenant1Flags).toBeDefined() + expect(tenant1Flags).toEqual([LICENSING]) + + expect(tenant2Flags).toBeDefined() + expect(tenant2Flags).toEqual([LICENSING, ONBOARDING_TOUR]) +}) + +it("Should explicitly add flags to configured tenants only", async () => { + env._set( + "TENANT_FEATURE_FLAGS", + `tenant1:${ONBOARDING_TOUR},tenant1:${LICENSING},tenant2:${LICENSING}` + ) + + let tenant1Flags = getTenantFeatureFlags("tenant1") + let tenant2Flags = getTenantFeatureFlags("tenant2") + + expect(tenant1Flags).toBeDefined() + expect(tenant1Flags).toEqual([ONBOARDING_TOUR, LICENSING]) + + expect(tenant2Flags).toBeDefined() + expect(tenant2Flags).toEqual([LICENSING]) +}) diff --git a/packages/backend-core/src/index.ts b/packages/backend-core/src/index.ts index a4d4ad0a80..b38a53e9e4 100644 --- a/packages/backend-core/src/index.ts +++ b/packages/backend-core/src/index.ts @@ -1,68 +1,42 @@ -import errors from "./errors" -const errorClasses = errors.errors -import * as events from "./events" -import * as migrations from "./migrations" -import * as users from "./users" -import * as roles from "./security/roles" -import * as permissions from "./security/permissions" -import * as accounts from "./cloud/accounts" -import * as installation from "./installation" -import env from "./environment" -import * as tenancy from "./tenancy" -import * as featureFlags from "./featureFlags" -import * as sessions from "./security/sessions" -import * as deprovisioning from "./context/deprovision" -import * as auth from "./auth" -import * as constants from "./constants" -import * as logging from "./logging" -import * as pino from "./pino" -import * as middleware from "./middleware" -import * as plugins from "./plugin" -import * as encryption from "./security/encryption" -import * as queue from "./queue" -import * as db from "./db" -import * as context from "./context" -import * as cache from "./cache" -import * as objectStore from "./objectStore" -import * as redis from "./redis" -import * as utils from "./utils" +export * as events from "./events" +export * as migrations from "./migrations" +export * as users from "./users" +export * as roles from "./security/roles" +export * as permissions from "./security/permissions" +export * as accounts from "./cloud/accounts" +export * as installation from "./installation" +export * as tenancy from "./tenancy" +export * as featureFlags from "./featureFlags" +export * as sessions from "./security/sessions" +export * as deprovisioning from "./context/deprovision" +export * as auth from "./auth" +export * as constants from "./constants" +export * as logging from "./logging" +export * as middleware from "./middleware" +export * as plugins from "./plugin" +export * as encryption from "./security/encryption" +export * as queue from "./queue" +export * as db from "./db" +export * as context from "./context" +export * as cache from "./cache" +export * as objectStore from "./objectStore" +export * as redis from "./redis" +export * as utils from "./utils" +export * as errors from "./errors" +export { default as env } from "./environment" -const init = (opts: any = {}) => { +// expose error classes directly +export * from "./errors" + +// expose constants directly +export * from "./constants" + +// expose inner locks from redis directly +import * as redis from "./redis" +export const locks = redis.redlock + +// expose package init function +import * as db from "./db" +export const init = (opts: any = {}) => { db.init(opts.db) } - -const core = { - init, - db, - ...constants, - redis, - locks: redis.redlock, - objectStore, - utils, - users, - cache, - auth, - constants, - migrations, - env, - accounts, - tenancy, - context, - featureFlags, - events, - sessions, - deprovisioning, - installation, - errors, - logging, - roles, - plugins, - ...pino, - ...errorClasses, - middleware, - encryption, - queue, - permissions, -} - -export = core diff --git a/packages/backend-core/src/logging.ts b/packages/backend-core/src/logging.ts index 3fc79a5fe7..8f2ae6e619 100644 --- a/packages/backend-core/src/logging.ts +++ b/packages/backend-core/src/logging.ts @@ -1,3 +1,9 @@ +import { Header } from "./constants" +import env from "./environment" +const correlator = require("correlation-id") +import { Options } from "pino-http" +import { IncomingMessage } from "http" + const NonErrors = ["AccountError"] function isSuppressed(e?: any) { @@ -29,8 +35,26 @@ export function logWarn(message: string) { console.warn(`bb-warn: ${message}`) } -export default { - logAlert, - logAlertWithInfo, - logWarn, +export function pinoSettings(): Options { + return { + prettyPrint: { + levelFirst: true, + }, + genReqId: correlator.getId, + level: env.LOG_LEVEL || "error", + autoLogging: { + ignore: (req: IncomingMessage) => !!req.url?.includes("/health"), + }, + } +} + +const setCorrelationHeader = (headers: any) => { + const correlationId = correlator.getId() + if (correlationId) { + headers[Header.CORRELATION_ID] = correlationId + } +} + +export const correlation = { + setHeader: setCorrelationHeader, } diff --git a/packages/backend-core/src/middleware/adminOnly.ts b/packages/backend-core/src/middleware/adminOnly.ts index 30fdf2907b..dbe1e3a501 100644 --- a/packages/backend-core/src/middleware/adminOnly.ts +++ b/packages/backend-core/src/middleware/adminOnly.ts @@ -1,6 +1,6 @@ import { BBContext } from "@budibase/types" -export = async (ctx: BBContext, next: any) => { +export default async (ctx: BBContext, next: any) => { if ( !ctx.internal && (!ctx.user || !ctx.user.admin || !ctx.user.admin.global) diff --git a/packages/backend-core/src/middleware/auditLog.ts b/packages/backend-core/src/middleware/auditLog.ts index a2c30ade8a..9b76bb10b7 100644 --- a/packages/backend-core/src/middleware/auditLog.ts +++ b/packages/backend-core/src/middleware/auditLog.ts @@ -1,6 +1,6 @@ import { BBContext } from "@budibase/types" -export = async (ctx: BBContext | any, next: any) => { +export default async (ctx: BBContext | any, next: any) => { // Placeholder for audit log middleware return next() } diff --git a/packages/backend-core/src/middleware/authenticated.ts b/packages/backend-core/src/middleware/authenticated.ts index fcf07c50a5..3b5e9ae162 100644 --- a/packages/backend-core/src/middleware/authenticated.ts +++ b/packages/backend-core/src/middleware/authenticated.ts @@ -66,7 +66,7 @@ async function checkApiKey(apiKey: string, populateUser?: Function) { * The tenancy modules should not be used here and it should be assumed that the tenancy context * has not yet been populated. */ -export = function ( +export default function ( noAuthPatterns: EndpointMatcher[] = [], opts: { publicAllowed?: boolean; populateUser?: Function } = { publicAllowed: false, diff --git a/packages/backend-core/src/middleware/builderOnly.ts b/packages/backend-core/src/middleware/builderOnly.ts index e13882d7f6..a00fd63a22 100644 --- a/packages/backend-core/src/middleware/builderOnly.ts +++ b/packages/backend-core/src/middleware/builderOnly.ts @@ -1,6 +1,6 @@ import { BBContext } from "@budibase/types" -export = async (ctx: BBContext, next: any) => { +export default async (ctx: BBContext, next: any) => { if ( !ctx.internal && (!ctx.user || !ctx.user.builder || !ctx.user.builder.global) diff --git a/packages/backend-core/src/middleware/builderOrAdmin.ts b/packages/backend-core/src/middleware/builderOrAdmin.ts index 26664695f8..26bb3a1bda 100644 --- a/packages/backend-core/src/middleware/builderOrAdmin.ts +++ b/packages/backend-core/src/middleware/builderOrAdmin.ts @@ -1,6 +1,6 @@ import { BBContext } from "@budibase/types" -export = async (ctx: BBContext, next: any) => { +export default async (ctx: BBContext, next: any) => { if ( !ctx.internal && (!ctx.user || !ctx.user.builder || !ctx.user.builder.global) && diff --git a/packages/backend-core/src/middleware/csrf.ts b/packages/backend-core/src/middleware/csrf.ts index 654ba47e07..cced4d5f7d 100644 --- a/packages/backend-core/src/middleware/csrf.ts +++ b/packages/backend-core/src/middleware/csrf.ts @@ -32,7 +32,7 @@ const INCLUDED_CONTENT_TYPES = [ * https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#synchronizer-token-pattern * */ -export = function ( +export default function ( opts: { noCsrfPatterns: EndpointMatcher[] } = { noCsrfPatterns: [] } ) { const noCsrfOptions = buildMatcherRegex(opts.noCsrfPatterns) diff --git a/packages/backend-core/src/middleware/index.ts b/packages/backend-core/src/middleware/index.ts index 2b332f5c49..4986cde64b 100644 --- a/packages/backend-core/src/middleware/index.ts +++ b/packages/backend-core/src/middleware/index.ts @@ -1,38 +1,19 @@ -import * as jwt from "./passport/jwt" -import * as local from "./passport/local" -import * as google from "./passport/google" -import * as oidc from "./passport/oidc" -import { authError, ssoCallbackUrl } from "./passport/utils" -import authenticated from "./authenticated" -import auditLog from "./auditLog" -import tenancy from "./tenancy" -import internalApi from "./internalApi" +export * as jwt from "./passport/jwt" +export * as local from "./passport/local" +export * as google from "./passport/google" +export * as oidc from "./passport/oidc" import * as datasourceGoogle from "./passport/datasource/google" -import csrf from "./csrf" -import adminOnly from "./adminOnly" -import builderOrAdmin from "./builderOrAdmin" -import builderOnly from "./builderOnly" -import * as joiValidator from "./joi-validator" - -const pkg = { - google, - oidc, - jwt, - local, - authenticated, - auditLog, - tenancy, - authError, - internalApi, - ssoCallbackUrl, - datasource: { - google: datasourceGoogle, - }, - csrf, - adminOnly, - builderOnly, - builderOrAdmin, - joiValidator, +export const datasource = { + google: datasourceGoogle, } - -export = pkg +export { authError, ssoCallbackUrl } from "./passport/utils" +export { default as authenticated } from "./authenticated" +export { default as auditLog } from "./auditLog" +export { default as tenancy } from "./tenancy" +export { default as internalApi } from "./internalApi" +export { default as csrf } from "./csrf" +export { default as adminOnly } from "./adminOnly" +export { default as builderOrAdmin } from "./builderOrAdmin" +export { default as builderOnly } from "./builderOnly" +export { default as logging } from "./logging" +export * as joiValidator from "./joi-validator" diff --git a/packages/backend-core/src/middleware/internalApi.ts b/packages/backend-core/src/middleware/internalApi.ts index f4f08ec2dd..fff761928b 100644 --- a/packages/backend-core/src/middleware/internalApi.ts +++ b/packages/backend-core/src/middleware/internalApi.ts @@ -5,7 +5,7 @@ import { BBContext } from "@budibase/types" /** * API Key only endpoint. */ -export = async (ctx: BBContext, next: any) => { +export default async (ctx: BBContext, next: any) => { const apiKey = ctx.request.headers[Header.API_KEY] if (apiKey !== env.INTERNAL_API_KEY) { ctx.throw(403, "Unauthorized") diff --git a/packages/backend-core/src/middleware/logging.ts b/packages/backend-core/src/middleware/logging.ts new file mode 100644 index 0000000000..d1f2d6566b --- /dev/null +++ b/packages/backend-core/src/middleware/logging.ts @@ -0,0 +1,88 @@ +const correlator = require("correlation-id") +import { Header } from "../constants" +import { v4 as uuid } from "uuid" +import * as context from "../context" + +const debug = console.warn +const trace = console.trace +const log = console.log +const info = console.info +const warn = console.warn +const error = console.error + +const getTenantId = () => { + let tenantId + try { + tenantId = context.getTenantId() + } catch (e: any) { + // do nothing + } + return tenantId +} + +const getAppId = () => { + let appId + try { + appId = context.getAppId() + } catch (e) { + // do nothing + } + return appId +} + +const getIdentityId = () => { + let identityId + try { + const identity = context.getIdentity() + identityId = identity?._id + } catch (e) { + // do nothing + } + return identityId +} + +const print = (fn: any, data: any[]) => { + let message = "" + + const correlationId = correlator.getId() + if (correlationId) { + message = message + `[correlationId=${correlator.getId()}]` + } + + const tenantId = getTenantId() + if (tenantId) { + message = message + ` [tenantId=${tenantId}]` + } + + const appId = getAppId() + if (appId) { + message = message + ` [appId=${appId}]` + } + + const identityId = getIdentityId() + if (identityId) { + message = message + ` [identityId=${identityId}]` + } + + fn(message, data) +} + +const logging = (ctx: any, next: any) => { + // use the provided correlation id header if present + let correlationId = ctx.headers[Header.CORRELATION_ID] + if (!correlationId) { + correlationId = uuid() + } + + return correlator.withId(correlationId, () => { + console.debug = data => print(debug, data) + console.trace = data => print(trace, data) + console.log = data => print(log, data) + console.info = data => print(info, data) + console.warn = data => print(warn, data) + console.error = data => print(error, data) + return next() + }) +} + +export default logging diff --git a/packages/backend-core/src/middleware/passport/oidc.ts b/packages/backend-core/src/middleware/passport/oidc.ts index 40bc22ec0c..7caa177cf0 100644 --- a/packages/backend-core/src/middleware/passport/oidc.ts +++ b/packages/backend-core/src/middleware/passport/oidc.ts @@ -2,7 +2,6 @@ import fetch from "node-fetch" import { authenticateThirdParty, SaveUserFunction } from "./third-party-common" import { ssoCallbackUrl } from "./utils" import { - Config, ConfigType, OIDCInnerCfg, Database, diff --git a/packages/backend-core/src/middleware/tenancy.ts b/packages/backend-core/src/middleware/tenancy.ts index 78da2bb3e8..a09c463045 100644 --- a/packages/backend-core/src/middleware/tenancy.ts +++ b/packages/backend-core/src/middleware/tenancy.ts @@ -8,7 +8,7 @@ import { TenantResolutionStrategy, } from "@budibase/types" -export = function ( +export default function ( allowQueryStringPatterns: EndpointMatcher[], noTenancyPatterns: EndpointMatcher[], opts: { noTenancyRequired?: boolean } = { noTenancyRequired: false } diff --git a/packages/backend-core/src/migrations/migrations.ts b/packages/backend-core/src/migrations/migrations.ts index 7bc2dec290..55b8ab1938 100644 --- a/packages/backend-core/src/migrations/migrations.ts +++ b/packages/backend-core/src/migrations/migrations.ts @@ -88,7 +88,7 @@ export const runMigration = async ( await doWithDB(dbName, async (db: any) => { try { - const doc = await exports.getMigrationsDoc(db) + const doc = await getMigrationsDoc(db) // the migration has already been run if (doc[migrationName]) { diff --git a/packages/backend-core/src/objectStore/buckets/app.ts b/packages/backend-core/src/objectStore/buckets/app.ts new file mode 100644 index 0000000000..9951058d6a --- /dev/null +++ b/packages/backend-core/src/objectStore/buckets/app.ts @@ -0,0 +1,40 @@ +import env from "../../environment" +import * as objectStore from "../objectStore" +import * as cloudfront from "../cloudfront" + +/** + * In production the client library is stored in the object store, however in development + * we use the symlinked version produced by lerna, located in node modules. We link to this + * via a specific endpoint (under /api/assets/client). + * @param {string} appId In production we need the appId to look up the correct bucket, as the + * version of the client lib may differ between apps. + * @param {string} version The version to retrieve. + * @return {string} The URL to be inserted into appPackage response or server rendered + * app index file. + */ +export const clientLibraryUrl = (appId: string, version: string) => { + if (env.isProd()) { + let file = `${objectStore.sanitizeKey(appId)}/budibase-client.js` + if (env.CLOUDFRONT_CDN) { + // append app version to bust the cache + if (version) { + file += `?v=${version}` + } + // don't need to use presigned for client with cloudfront + // file is public + return cloudfront.getUrl(file) + } else { + return objectStore.getPresignedUrl(env.APPS_BUCKET_NAME, file) + } + } else { + return `/api/assets/client` + } +} + +export const getAppFileUrl = (s3Key: string) => { + if (env.CLOUDFRONT_CDN) { + return cloudfront.getPresignedUrl(s3Key) + } else { + return objectStore.getPresignedUrl(env.APPS_BUCKET_NAME, s3Key) + } +} diff --git a/packages/backend-core/src/objectStore/buckets/global.ts b/packages/backend-core/src/objectStore/buckets/global.ts new file mode 100644 index 0000000000..8bf883b11e --- /dev/null +++ b/packages/backend-core/src/objectStore/buckets/global.ts @@ -0,0 +1,29 @@ +import env from "../../environment" +import * as tenancy from "../../tenancy" +import * as objectStore from "../objectStore" +import * as cloudfront from "../cloudfront" + +// URLs + +export const getGlobalFileUrl = (type: string, name: string, etag?: string) => { + let file = getGlobalFileS3Key(type, name) + if (env.CLOUDFRONT_CDN) { + if (etag) { + file = `${file}?etag=${etag}` + } + return cloudfront.getPresignedUrl(file) + } else { + return objectStore.getPresignedUrl(env.GLOBAL_BUCKET_NAME, file) + } +} + +// KEYS + +export const getGlobalFileS3Key = (type: string, name: string) => { + let file = `${type}/${name}` + if (env.MULTI_TENANCY) { + const tenantId = tenancy.getTenantId() + file = `${tenantId}/${file}` + } + return file +} diff --git a/packages/backend-core/src/objectStore/buckets/index.ts b/packages/backend-core/src/objectStore/buckets/index.ts new file mode 100644 index 0000000000..8398242ee5 --- /dev/null +++ b/packages/backend-core/src/objectStore/buckets/index.ts @@ -0,0 +1,3 @@ +export * from "./app" +export * from "./global" +export * from "./plugins" diff --git a/packages/backend-core/src/objectStore/buckets/plugins.ts b/packages/backend-core/src/objectStore/buckets/plugins.ts new file mode 100644 index 0000000000..cd3bf77e87 --- /dev/null +++ b/packages/backend-core/src/objectStore/buckets/plugins.ts @@ -0,0 +1,71 @@ +import env from "../../environment" +import * as objectStore from "../objectStore" +import * as tenancy from "../../tenancy" +import * as cloudfront from "../cloudfront" +import { Plugin } from "@budibase/types" + +// URLS + +export const enrichPluginURLs = (plugins: Plugin[]) => { + if (!plugins || !plugins.length) { + return [] + } + return plugins.map(plugin => { + const jsUrl = getPluginJSUrl(plugin) + const iconUrl = getPluginIconUrl(plugin) + return { ...plugin, jsUrl, iconUrl } + }) +} + +const getPluginJSUrl = (plugin: Plugin) => { + const s3Key = getPluginJSKey(plugin) + return getPluginUrl(s3Key) +} + +const getPluginIconUrl = (plugin: Plugin): string | undefined => { + const s3Key = getPluginIconKey(plugin) + if (!s3Key) { + return + } + return getPluginUrl(s3Key) +} + +const getPluginUrl = (s3Key: string) => { + if (env.CLOUDFRONT_CDN) { + return cloudfront.getPresignedUrl(s3Key) + } else { + return objectStore.getPresignedUrl(env.PLUGIN_BUCKET_NAME, s3Key) + } +} + +// S3 KEYS + +export const getPluginJSKey = (plugin: Plugin) => { + return getPluginS3Key(plugin, "plugin.min.js") +} + +export const getPluginIconKey = (plugin: Plugin) => { + // stored iconUrl is deprecated - hardcode to icon.svg in this case + const iconFileName = plugin.iconUrl ? "icon.svg" : plugin.iconFileName + if (!iconFileName) { + return + } + return getPluginS3Key(plugin, iconFileName) +} + +const getPluginS3Key = (plugin: Plugin, fileName: string) => { + const s3Key = getPluginS3Dir(plugin.name) + return `${s3Key}/${fileName}` +} + +export const getPluginS3Dir = (pluginName: string) => { + let s3Key = `${pluginName}` + if (env.MULTI_TENANCY) { + const tenantId = tenancy.getTenantId() + s3Key = `${tenantId}/${s3Key}` + } + if (env.CLOUDFRONT_CDN) { + s3Key = `plugins/${s3Key}` + } + return s3Key +} diff --git a/packages/backend-core/src/objectStore/buckets/tests/app.spec.ts b/packages/backend-core/src/objectStore/buckets/tests/app.spec.ts new file mode 100644 index 0000000000..0375e97cbc --- /dev/null +++ b/packages/backend-core/src/objectStore/buckets/tests/app.spec.ts @@ -0,0 +1,171 @@ +import * as app from "../app" +import { getAppFileUrl } from "../app" +import { testEnv } from "../../../../tests" + +describe("app", () => { + beforeEach(() => { + testEnv.nodeJest() + }) + + describe("clientLibraryUrl", () => { + function getClientUrl() { + return app.clientLibraryUrl("app_123/budibase-client.js", "2.0.0") + } + + describe("single tenant", () => { + beforeAll(() => { + testEnv.singleTenant() + }) + + it("gets url in dev", () => { + testEnv.nodeDev() + const url = getClientUrl() + expect(url).toBe("/api/assets/client") + }) + + it("gets url with embedded minio", () => { + testEnv.withMinio() + const url = getClientUrl() + expect(url).toBe( + "/files/signed/prod-budi-app-assets/app_123/budibase-client.js/budibase-client.js" + ) + }) + + it("gets url with custom S3", () => { + testEnv.withS3() + const url = getClientUrl() + expect(url).toBe( + "http://s3.example.com/prod-budi-app-assets/app_123/budibase-client.js/budibase-client.js" + ) + }) + + it("gets url with cloudfront + s3", () => { + testEnv.withCloudfront() + const url = getClientUrl() + expect(url).toBe( + "http://cf.example.com/app_123/budibase-client.js/budibase-client.js?v=2.0.0" + ) + }) + }) + + describe("multi tenant", () => { + beforeAll(() => { + testEnv.multiTenant() + }) + + it("gets url in dev", async () => { + testEnv.nodeDev() + await testEnv.withTenant(tenantId => { + const url = getClientUrl() + expect(url).toBe("/api/assets/client") + }) + }) + + it("gets url with embedded minio", async () => { + await testEnv.withTenant(tenantId => { + testEnv.withMinio() + const url = getClientUrl() + expect(url).toBe( + "/files/signed/prod-budi-app-assets/app_123/budibase-client.js/budibase-client.js" + ) + }) + }) + + it("gets url with custom S3", async () => { + await testEnv.withTenant(tenantId => { + testEnv.withS3() + const url = getClientUrl() + expect(url).toBe( + "http://s3.example.com/prod-budi-app-assets/app_123/budibase-client.js/budibase-client.js" + ) + }) + }) + + it("gets url with cloudfront + s3", async () => { + await testEnv.withTenant(tenantId => { + testEnv.withCloudfront() + const url = getClientUrl() + expect(url).toBe( + "http://cf.example.com/app_123/budibase-client.js/budibase-client.js?v=2.0.0" + ) + }) + }) + }) + }) + + describe("getAppFileUrl", () => { + function getAppFileUrl() { + return app.getAppFileUrl("app_123/attachments/image.jpeg") + } + + describe("single tenant", () => { + beforeAll(() => { + testEnv.multiTenant() + }) + + it("gets url with embedded minio", () => { + testEnv.withMinio() + const url = getAppFileUrl() + expect(url).toBe( + "/files/signed/prod-budi-app-assets/app_123/attachments/image.jpeg" + ) + }) + + it("gets url with custom S3", () => { + testEnv.withS3() + const url = getAppFileUrl() + expect(url).toBe( + "http://s3.example.com/prod-budi-app-assets/app_123/attachments/image.jpeg" + ) + }) + + it("gets url with cloudfront + s3", () => { + testEnv.withCloudfront() + const url = getAppFileUrl() + // omit rest of signed params + expect( + url.includes("http://cf.example.com/app_123/attachments/image.jpeg?") + ).toBe(true) + }) + }) + + describe("multi tenant", () => { + beforeAll(() => { + testEnv.multiTenant() + }) + + it("gets url with embedded minio", async () => { + testEnv.withMinio() + await testEnv.withTenant(tenantId => { + const url = getAppFileUrl() + expect(url).toBe( + "/files/signed/prod-budi-app-assets/app_123/attachments/image.jpeg" + ) + }) + }) + + it("gets url with custom S3", async () => { + testEnv.withS3() + await testEnv.withTenant(tenantId => { + const url = getAppFileUrl() + expect(url).toBe( + "http://s3.example.com/prod-budi-app-assets/app_123/attachments/image.jpeg" + ) + }) + }) + + it("gets url with cloudfront + s3", async () => { + testEnv.withCloudfront() + await testEnv.withTenant(tenantId => { + const url = getAppFileUrl() + // omit rest of signed params + expect( + url.includes( + "http://cf.example.com/app_123/attachments/image.jpeg?" + ) + ).toBe(true) + }) + }) + }) + }) +}) diff --git a/packages/backend-core/src/objectStore/buckets/tests/global.spec.ts b/packages/backend-core/src/objectStore/buckets/tests/global.spec.ts new file mode 100644 index 0000000000..b495812356 --- /dev/null +++ b/packages/backend-core/src/objectStore/buckets/tests/global.spec.ts @@ -0,0 +1,74 @@ +import * as global from "../global" +import { testEnv } from "../../../../tests" + +describe("global", () => { + describe("getGlobalFileUrl", () => { + function getGlobalFileUrl() { + return global.getGlobalFileUrl("settings", "logoUrl", "etag") + } + + describe("single tenant", () => { + beforeAll(() => { + testEnv.singleTenant() + }) + + it("gets url with embedded minio", () => { + testEnv.withMinio() + const url = getGlobalFileUrl() + expect(url).toBe("/files/signed/global/settings/logoUrl") + }) + + it("gets url with custom S3", () => { + testEnv.withS3() + const url = getGlobalFileUrl() + expect(url).toBe("http://s3.example.com/global/settings/logoUrl") + }) + + it("gets url with cloudfront + s3", () => { + testEnv.withCloudfront() + const url = getGlobalFileUrl() + // omit rest of signed params + expect( + url.includes("http://cf.example.com/settings/logoUrl?etag=etag&") + ).toBe(true) + }) + }) + + describe("multi tenant", () => { + beforeAll(() => { + testEnv.multiTenant() + }) + + it("gets url with embedded minio", async () => { + testEnv.withMinio() + await testEnv.withTenant(tenantId => { + const url = getGlobalFileUrl() + expect(url).toBe(`/files/signed/global/${tenantId}/settings/logoUrl`) + }) + }) + + it("gets url with custom S3", async () => { + testEnv.withS3() + await testEnv.withTenant(tenantId => { + const url = getGlobalFileUrl() + expect(url).toBe( + `http://s3.example.com/global/${tenantId}/settings/logoUrl` + ) + }) + }) + + it("gets url with cloudfront + s3", async () => { + testEnv.withCloudfront() + await testEnv.withTenant(tenantId => { + const url = getGlobalFileUrl() + // omit rest of signed params + expect( + url.includes( + `http://cf.example.com/${tenantId}/settings/logoUrl?etag=etag&` + ) + ).toBe(true) + }) + }) + }) + }) +}) diff --git a/packages/backend-core/src/objectStore/buckets/tests/plugins.spec.ts b/packages/backend-core/src/objectStore/buckets/tests/plugins.spec.ts new file mode 100644 index 0000000000..affb8d8318 --- /dev/null +++ b/packages/backend-core/src/objectStore/buckets/tests/plugins.spec.ts @@ -0,0 +1,110 @@ +import * as plugins from "../plugins" +import { structures, testEnv } from "../../../../tests" + +describe("plugins", () => { + describe("enrichPluginURLs", () => { + const plugin = structures.plugins.plugin() + + function getEnrichedPluginUrls() { + const enriched = plugins.enrichPluginURLs([plugin])[0] + return { + jsUrl: enriched.jsUrl!, + iconUrl: enriched.iconUrl!, + } + } + + describe("single tenant", () => { + beforeAll(() => { + testEnv.singleTenant() + }) + + it("gets url with embedded minio", () => { + testEnv.withMinio() + const urls = getEnrichedPluginUrls() + expect(urls.jsUrl).toBe( + `/files/signed/plugins/${plugin.name}/plugin.min.js` + ) + expect(urls.iconUrl).toBe( + `/files/signed/plugins/${plugin.name}/icon.svg` + ) + }) + + it("gets url with custom S3", () => { + testEnv.withS3() + const urls = getEnrichedPluginUrls() + expect(urls.jsUrl).toBe( + `http://s3.example.com/plugins/${plugin.name}/plugin.min.js` + ) + expect(urls.iconUrl).toBe( + `http://s3.example.com/plugins/${plugin.name}/icon.svg` + ) + }) + + it("gets url with cloudfront + s3", () => { + testEnv.withCloudfront() + const urls = getEnrichedPluginUrls() + // omit rest of signed params + expect( + urls.jsUrl.includes( + `http://cf.example.com/plugins/${plugin.name}/plugin.min.js?` + ) + ).toBe(true) + expect( + urls.iconUrl.includes( + `http://cf.example.com/plugins/${plugin.name}/icon.svg?` + ) + ).toBe(true) + }) + }) + + describe("multi tenant", () => { + beforeAll(() => { + testEnv.multiTenant() + }) + + it("gets url with embedded minio", async () => { + testEnv.withMinio() + await testEnv.withTenant(tenantId => { + const urls = getEnrichedPluginUrls() + expect(urls.jsUrl).toBe( + `/files/signed/plugins/${tenantId}/${plugin.name}/plugin.min.js` + ) + expect(urls.iconUrl).toBe( + `/files/signed/plugins/${tenantId}/${plugin.name}/icon.svg` + ) + }) + }) + + it("gets url with custom S3", async () => { + testEnv.withS3() + await testEnv.withTenant(tenantId => { + const urls = getEnrichedPluginUrls() + expect(urls.jsUrl).toBe( + `http://s3.example.com/plugins/${tenantId}/${plugin.name}/plugin.min.js` + ) + expect(urls.iconUrl).toBe( + `http://s3.example.com/plugins/${tenantId}/${plugin.name}/icon.svg` + ) + }) + }) + + it("gets url with cloudfront + s3", async () => { + testEnv.withCloudfront() + await testEnv.withTenant(tenantId => { + const urls = getEnrichedPluginUrls() + // omit rest of signed params + expect( + urls.jsUrl.includes( + `http://cf.example.com/plugins/${tenantId}/${plugin.name}/plugin.min.js?` + ) + ).toBe(true) + expect( + urls.iconUrl.includes( + `http://cf.example.com/plugins/${tenantId}/${plugin.name}/icon.svg?` + ) + ).toBe(true) + }) + }) + }) + }) +}) diff --git a/packages/backend-core/src/objectStore/cloudfront.ts b/packages/backend-core/src/objectStore/cloudfront.ts new file mode 100644 index 0000000000..a61ea7f583 --- /dev/null +++ b/packages/backend-core/src/objectStore/cloudfront.ts @@ -0,0 +1,41 @@ +import env from "../environment" +const cfsign = require("aws-cloudfront-sign") + +let PRIVATE_KEY: string | undefined + +function getPrivateKey() { + if (!env.CLOUDFRONT_PRIVATE_KEY_64) { + throw new Error("CLOUDFRONT_PRIVATE_KEY_64 is not set") + } + + if (PRIVATE_KEY) { + return PRIVATE_KEY + } + + PRIVATE_KEY = Buffer.from(env.CLOUDFRONT_PRIVATE_KEY_64, "base64").toString( + "utf-8" + ) + + return PRIVATE_KEY +} + +const getCloudfrontSignParams = () => { + return { + keypairId: env.CLOUDFRONT_PUBLIC_KEY_ID, + privateKeyString: getPrivateKey(), + expireTime: new Date().getTime() + 1000 * 60 * 60, // 1 hour + } +} + +export const getPresignedUrl = (s3Key: string) => { + const url = getUrl(s3Key) + return cfsign.getSignedUrl(url, getCloudfrontSignParams()) +} + +export const getUrl = (s3Key: string) => { + let prefix = "/" + if (s3Key.startsWith("/")) { + prefix = "" + } + return `${env.CLOUDFRONT_CDN}${prefix}${s3Key}` +} diff --git a/packages/backend-core/src/objectStore/index.ts b/packages/backend-core/src/objectStore/index.ts index 2971834f0e..02c99828dd 100644 --- a/packages/backend-core/src/objectStore/index.ts +++ b/packages/backend-core/src/objectStore/index.ts @@ -1,2 +1,3 @@ export * from "./objectStore" export * from "./utils" +export * from "./buckets" diff --git a/packages/backend-core/src/objectStore/objectStore.ts b/packages/backend-core/src/objectStore/objectStore.ts index 2ae8848c53..f601d40a37 100644 --- a/packages/backend-core/src/objectStore/objectStore.ts +++ b/packages/backend-core/src/objectStore/objectStore.ts @@ -8,7 +8,7 @@ import { promisify } from "util" import { join } from "path" import fs from "fs" import env from "../environment" -import { budibaseTempDir, ObjectStoreBuckets } from "./utils" +import { budibaseTempDir } from "./utils" import { v4 } from "uuid" import { APP_PREFIX, APP_DEV_PREFIX } from "../db" @@ -26,7 +26,7 @@ type UploadParams = { bucket: string filename: string path: string - type?: string + type?: string | null // can be undefined, we will remove it metadata?: { [key: string]: string | undefined @@ -41,6 +41,7 @@ const CONTENT_TYPE_MAP: any = { json: "application/json", gz: "application/gzip", } + const STRING_CONTENT_TYPES = [ CONTENT_TYPE_MAP.html, CONTENT_TYPE_MAP.css, @@ -58,35 +59,17 @@ export function sanitizeBucket(input: string) { return input.replace(new RegExp(APP_DEV_PREFIX, "g"), APP_PREFIX) } -function publicPolicy(bucketName: string) { - return { - Version: "2012-10-17", - Statement: [ - { - Effect: "Allow", - Principal: { - AWS: ["*"], - }, - Action: "s3:GetObject", - Resource: [`arn:aws:s3:::${bucketName}/*`], - }, - ], - } -} - -const PUBLIC_BUCKETS = [ - ObjectStoreBuckets.APPS, - ObjectStoreBuckets.GLOBAL, - ObjectStoreBuckets.PLUGINS, -] - /** * Gets a connection to the object store using the S3 SDK. * @param {string} bucket the name of the bucket which blobs will be uploaded/retrieved from. + * @param {object} opts configuration for the object store. * @return {Object} an S3 object store object, check S3 Nodejs SDK for usage. * @constructor */ -export const ObjectStore = (bucket: string) => { +export const ObjectStore = ( + bucket: string, + opts: { presigning: boolean } = { presigning: false } +) => { const config: any = { s3ForcePathStyle: true, signatureVersion: "v4", @@ -100,9 +83,20 @@ export const ObjectStore = (bucket: string) => { Bucket: sanitizeBucket(bucket), } } + + // custom S3 is in use i.e. minio if (env.MINIO_URL) { - config.endpoint = env.MINIO_URL + if (opts.presigning && env.MINIO_ENABLED) { + // IMPORTANT: Signed urls will inspect the host header of the request. + // Normally a signed url will need to be generated with a specified host in mind. + // To support dynamic hosts, e.g. some unknown self-hosted installation url, + // use a predefined host. The host 'minio-service' is also forwarded to minio requests via nginx + config.endpoint = "minio-service" + } else { + config.endpoint = env.MINIO_URL + } } + return new AWS.S3(config) } @@ -135,16 +129,6 @@ export const makeSureBucketExists = async (client: any, bucketName: string) => { await promises[bucketName] delete promises[bucketName] } - // public buckets are quite hidden in the system, make sure - // no bucket is set accidentally - if (PUBLIC_BUCKETS.includes(bucketName)) { - await client - .putBucketPolicy({ - Bucket: bucketName, - Policy: JSON.stringify(publicPolicy(bucketName)), - }) - .promise() - } } else { throw new Error("Unable to write to object store bucket.") } @@ -274,6 +258,36 @@ export const listAllObjects = async (bucketName: string, path: string) => { return objects } +/** + * Generate a presigned url with a default TTL of 1 hour + */ +export const getPresignedUrl = ( + bucketName: string, + key: string, + durationSeconds: number = 3600 +) => { + const objectStore = ObjectStore(bucketName, { presigning: true }) + const params = { + Bucket: sanitizeBucket(bucketName), + Key: sanitizeKey(key), + Expires: durationSeconds, + } + const url = objectStore.getSignedUrl("getObject", params) + + if (!env.MINIO_ENABLED) { + // return the full URL to the client + return url + } else { + // return the path only to the client + // use the presigned url route to ensure the static + // hostname will be used in the request + const signedUrl = new URL(url) + const path = signedUrl.pathname + const query = signedUrl.search + return `/files/signed${path}${query}` + } +} + /** * Same as retrieval function but puts to a temporary file. */ @@ -315,9 +329,9 @@ export const deleteFile = async (bucketName: string, filepath: string) => { await makeSureBucketExists(objectStore, bucketName) const params = { Bucket: bucketName, - Key: filepath, + Key: sanitizeKey(filepath), } - return objectStore.deleteObject(params) + return objectStore.deleteObject(params).promise() } export const deleteFiles = async (bucketName: string, filepaths: string[]) => { @@ -326,7 +340,7 @@ export const deleteFiles = async (bucketName: string, filepaths: string[]) => { const params = { Bucket: bucketName, Delete: { - Objects: filepaths.map((path: any) => ({ Key: path })), + Objects: filepaths.map((path: any) => ({ Key: sanitizeKey(path) })), }, } return objectStore.deleteObjects(params).promise() diff --git a/packages/backend-core/src/objectStore/utils.ts b/packages/backend-core/src/objectStore/utils.ts index f3c9e93943..dba5f3d1c2 100644 --- a/packages/backend-core/src/objectStore/utils.ts +++ b/packages/backend-core/src/objectStore/utils.ts @@ -14,7 +14,6 @@ export const ObjectStoreBuckets = { APPS: env.APPS_BUCKET_NAME, TEMPLATES: env.TEMPLATES_BUCKET_NAME, GLOBAL: env.GLOBAL_BUCKET_NAME, - GLOBAL_CLOUD: env.GLOBAL_CLOUD_BUCKET_NAME, PLUGINS: env.PLUGIN_BUCKET_NAME, } diff --git a/packages/backend-core/src/pino.ts b/packages/backend-core/src/pino.ts deleted file mode 100644 index 4140f428e1..0000000000 --- a/packages/backend-core/src/pino.ts +++ /dev/null @@ -1,13 +0,0 @@ -import env from "./environment" - -export function pinoSettings() { - return { - prettyPrint: { - levelFirst: true, - }, - level: env.LOG_LEVEL || "error", - autoLogging: { - ignore: (req: { url: string }) => req.url.includes("/health"), - }, - } -} diff --git a/packages/backend-core/src/queue/inMemoryQueue.ts b/packages/backend-core/src/queue/inMemoryQueue.ts index acfff1c7b8..b80aece418 100644 --- a/packages/backend-core/src/queue/inMemoryQueue.ts +++ b/packages/backend-core/src/queue/inMemoryQueue.ts @@ -137,4 +137,4 @@ class InMemoryQueue { } } -export = InMemoryQueue +export default InMemoryQueue diff --git a/packages/backend-core/src/redis/redis.ts b/packages/backend-core/src/redis/redis.ts index 58734fc4f1..0267709cdc 100644 --- a/packages/backend-core/src/redis/redis.ts +++ b/packages/backend-core/src/redis/redis.ts @@ -276,4 +276,4 @@ class RedisWrapper { } } -export = RedisWrapper +export default RedisWrapper diff --git a/packages/backend-core/src/security/encryption.ts b/packages/backend-core/src/security/encryption.ts index a9006f302d..d0707cb850 100644 --- a/packages/backend-core/src/security/encryption.ts +++ b/packages/backend-core/src/security/encryption.ts @@ -2,19 +2,45 @@ import crypto from "crypto" import env from "../environment" const ALGO = "aes-256-ctr" -const SECRET = env.JWT_SECRET const SEPARATOR = "-" const ITERATIONS = 10000 const RANDOM_BYTES = 16 const STRETCH_LENGTH = 32 +export enum SecretOption { + JWT = "jwt", + ENCRYPTION = "encryption", +} + +function getSecret(secretOption: SecretOption): string { + let secret, secretName + switch (secretOption) { + case SecretOption.ENCRYPTION: + secret = env.ENCRYPTION_KEY + secretName = "ENCRYPTION_KEY" + break + case SecretOption.JWT: + default: + secret = env.JWT_SECRET + secretName = "JWT_SECRET" + break + } + if (!secret) { + throw new Error(`Secret "${secretName}" has not been set in environment.`) + } + return secret +} + function stretchString(string: string, salt: Buffer) { return crypto.pbkdf2Sync(string, salt, ITERATIONS, STRETCH_LENGTH, "sha512") } -export function encrypt(input: string) { +export function encrypt( + input: string, + secretOption: SecretOption = SecretOption.JWT +) { const salt = crypto.randomBytes(RANDOM_BYTES) - const stretched = stretchString(SECRET!, salt) + const stretched = stretchString(getSecret(secretOption), salt) const cipher = crypto.createCipheriv(ALGO, stretched, salt) const base = cipher.update(input) const final = cipher.final() @@ -22,10 +48,13 @@ export function encrypt(input: string) { return `${salt.toString("hex")}${SEPARATOR}${encrypted}` } -export function decrypt(input: string) { +export function decrypt( + input: string, + secretOption: SecretOption = SecretOption.JWT +) { const [salt, encrypted] = input.split(SEPARATOR) const saltBuffer = Buffer.from(salt, "hex") - const stretched = stretchString(SECRET!, saltBuffer) + const stretched = stretchString(getSecret(secretOption), saltBuffer) const decipher = crypto.createDecipheriv(ALGO, stretched, saltBuffer) const base = decipher.update(Buffer.from(encrypted, "hex")) const final = decipher.final() diff --git a/packages/backend-core/src/security/sessions.ts b/packages/backend-core/src/security/sessions.ts index 48e75b0d60..5a535c0c46 100644 --- a/packages/backend-core/src/security/sessions.ts +++ b/packages/backend-core/src/security/sessions.ts @@ -1,7 +1,7 @@ const redis = require("../redis/init") const { v4: uuidv4 } = require("uuid") const { logWarn } = require("../logging") -const env = require("../environment") +import env from "../environment" import { Session, ScannedSession, diff --git a/packages/backend-core/src/tenancy/tenancy.ts b/packages/backend-core/src/tenancy/tenancy.ts index e0e0703433..732402bcb7 100644 --- a/packages/backend-core/src/tenancy/tenancy.ts +++ b/packages/backend-core/src/tenancy/tenancy.ts @@ -1,4 +1,4 @@ -import { doWithDB, queryPlatformView, getGlobalDBName } from "../db" +import { doWithDB, getGlobalDBName } from "../db" import { DEFAULT_TENANT_ID, getTenantId, @@ -8,11 +8,10 @@ import { import env from "../environment" import { BBContext, - PlatformUser, TenantResolutionStrategy, GetTenantIdOptions, } from "@budibase/types" -import { Header, StaticDatabases, ViewName } from "../constants" +import { Header, StaticDatabases } from "../constants" const TENANT_DOC = StaticDatabases.PLATFORM_INFO.docs.tenants const PLATFORM_INFO_DB = StaticDatabases.PLATFORM_INFO.name @@ -111,27 +110,7 @@ export async function lookupTenantId(userId: string) { }) } -// lookup, could be email or userId, either will return a doc -export async function getTenantUser( - identifier: string -): Promise { - // use the view here and allow to find anyone regardless of casing - // Use lowercase to ensure email login is case-insensitive - const users = await queryPlatformView( - ViewName.PLATFORM_USERS_LOWERCASE, - { - keys: [identifier.toLowerCase()], - include_docs: true, - } - ) - if (Array.isArray(users)) { - return users[0] - } else { - return users - } -} - -export function isUserInAppTenant(appId: string, user?: any) { +export const isUserInAppTenant = (appId: string, user?: any) => { let userTenantId if (user) { userTenantId = user.tenantId || DEFAULT_TENANT_ID diff --git a/packages/backend-core/src/tests/utils.spec.js b/packages/backend-core/src/tests/utils.spec.js deleted file mode 100644 index fb3828921d..0000000000 --- a/packages/backend-core/src/tests/utils.spec.js +++ /dev/null @@ -1,17 +0,0 @@ -const { structures } = require("../../tests") -const utils = require("../utils") -const events = require("../events") -const { DEFAULT_TENANT_ID } = require("../constants") -const { doInTenant } = require("../context") - -describe("utils", () => { - describe("platformLogout", () => { - it("should call platform logout", async () => { - await doInTenant(DEFAULT_TENANT_ID, async () => { - const ctx = structures.koa.newContext() - await utils.platformLogout({ ctx, userId: "test" }) - expect(events.auth.logout).toBeCalledTimes(1) - }) - }) - }) -}) \ No newline at end of file diff --git a/packages/backend-core/src/utils/tests/utils.spec.ts b/packages/backend-core/src/utils/tests/utils.spec.ts new file mode 100644 index 0000000000..498aff1555 --- /dev/null +++ b/packages/backend-core/src/utils/tests/utils.spec.ts @@ -0,0 +1,109 @@ +import { structures } from "../../../tests" +import * as utils from "../../utils" +import * as events from "../../events" +import * as db from "../../db" +import { DEFAULT_TENANT_ID, Header } from "../../constants" +import { doInTenant } from "../../context" + +describe("utils", () => { + describe("platformLogout", () => { + it("should call platform logout", async () => { + await doInTenant(DEFAULT_TENANT_ID, async () => { + const ctx = structures.koa.newContext() + await utils.platformLogout({ ctx, userId: "test" }) + expect(events.auth.logout).toBeCalledTimes(1) + }) + }) + }) + + describe("getAppIdFromCtx", () => { + it("gets appId from header", async () => { + const ctx = structures.koa.newContext() + const expected = db.generateAppID() + ctx.request.headers = { + [Header.APP_ID]: expected, + } + + const actual = await utils.getAppIdFromCtx(ctx) + expect(actual).toBe(expected) + }) + + it("gets appId from body", async () => { + const ctx = structures.koa.newContext() + const expected = db.generateAppID() + ctx.request.body = { + appId: expected, + } + + const actual = await utils.getAppIdFromCtx(ctx) + expect(actual).toBe(expected) + }) + + it("gets appId from path", async () => { + const ctx = structures.koa.newContext() + const expected = db.generateAppID() + ctx.path = `/apps/${expected}` + + const actual = await utils.getAppIdFromCtx(ctx) + expect(actual).toBe(expected) + }) + + it("gets appId from url", async () => { + const ctx = structures.koa.newContext() + const expected = db.generateAppID() + const app = structures.apps.app(expected) + + // set custom url + const appUrl = "custom-url" + app.url = `/${appUrl}` + ctx.path = `/app/${appUrl}` + + // save the app + const database = db.getDB(expected) + await database.put(app) + + const actual = await utils.getAppIdFromCtx(ctx) + expect(actual).toBe(expected) + }) + + it("doesn't get appId from url when previewing", async () => { + const ctx = structures.koa.newContext() + const appId = db.generateAppID() + const app = structures.apps.app(appId) + + // set custom url + const appUrl = "preview" + app.url = `/${appUrl}` + ctx.path = `/app/${appUrl}` + + // save the app + const database = db.getDB(appId) + await database.put(app) + + const actual = await utils.getAppIdFromCtx(ctx) + expect(actual).toBe(undefined) + }) + + it("gets appId from referer", async () => { + const ctx = structures.koa.newContext() + const expected = db.generateAppID() + ctx.request.headers = { + referer: `http://test.com/builder/app/${expected}/design/screen_123/screens`, + } + + const actual = await utils.getAppIdFromCtx(ctx) + expect(actual).toBe(expected) + }) + + it("doesn't get appId from referer when not builder", async () => { + const ctx = structures.koa.newContext() + const appId = db.generateAppID() + ctx.request.headers = { + referer: `http://test.com/foo/app/${appId}/bar`, + } + + const actual = await utils.getAppIdFromCtx(ctx) + expect(actual).toBe(undefined) + }) + }) +}) diff --git a/packages/backend-core/src/utils/utils.ts b/packages/backend-core/src/utils/utils.ts index 3e9fbb177a..c608686431 100644 --- a/packages/backend-core/src/utils/utils.ts +++ b/packages/backend-core/src/utils/utils.ts @@ -1,6 +1,13 @@ import { getAllApps, queryGlobalView } from "../db" import { options } from "../middleware/passport/jwt" -import { Header, Cookie, MAX_VALID_DATE } from "../constants" +import { + Header, + Cookie, + MAX_VALID_DATE, + DocumentType, + SEPARATOR, + ViewName, +} from "../constants" import env from "../environment" import * as userCache from "../cache/user" import { getSessionsForUser, invalidateSessions } from "../security/sessions" @@ -8,24 +15,26 @@ import * as events from "../events" import * as tenancy from "../tenancy" import { App, - BBContext, + Ctx, PlatformLogoutOpts, TenantResolutionStrategy, } from "@budibase/types" import { SetOption } from "cookies" -import { DocumentType, SEPARATOR, ViewName } from "../constants" const jwt = require("jsonwebtoken") const APP_PREFIX = DocumentType.APP + SEPARATOR const PROD_APP_PREFIX = "/app/" +const BUILDER_PREVIEW_PATH = "/app/preview" +const BUILDER_REFERER_PREFIX = "/builder/app/" + function confirmAppId(possibleAppId: string | undefined) { return possibleAppId && possibleAppId.startsWith(APP_PREFIX) ? possibleAppId : undefined } -async function resolveAppUrl(ctx: BBContext) { +export async function resolveAppUrl(ctx: Ctx) { const appUrl = ctx.path.split("/")[2] let possibleAppUrl = `/${appUrl.toLowerCase()}` @@ -50,7 +59,7 @@ async function resolveAppUrl(ctx: BBContext) { return app && app.appId ? app.appId : undefined } -export function isServingApp(ctx: BBContext) { +export function isServingApp(ctx: Ctx) { // dev app if (ctx.path.startsWith(`/${APP_PREFIX}`)) { return true @@ -67,9 +76,9 @@ export function isServingApp(ctx: BBContext) { * @param {object} ctx The main request body to look through. * @returns {string|undefined} If an appId was found it will be returned. */ -export async function getAppIdFromCtx(ctx: BBContext) { +export async function getAppIdFromCtx(ctx: Ctx) { // look in headers - const options = [ctx.headers[Header.APP_ID]] + const options = [ctx.request.headers[Header.APP_ID]] let appId for (let option of options) { appId = confirmAppId(option as string) @@ -83,22 +92,41 @@ export async function getAppIdFromCtx(ctx: BBContext) { appId = confirmAppId(ctx.request.body.appId) } - // look in the url - dev app - let appPath = - ctx.request.headers.referrer || - ctx.path.split("/").filter(subPath => subPath.startsWith(APP_PREFIX)) - if (!appId && appPath.length) { - appId = confirmAppId(appPath[0]) + // look in the path + const pathId = parseAppIdFromUrl(ctx.path) + if (!appId && pathId) { + appId = confirmAppId(pathId) } - // look in the url - prod app - if (!appId && ctx.path.startsWith(PROD_APP_PREFIX)) { + // lookup using custom url - prod apps only + // filter out the builder preview path which collides with the prod app path + // to ensure we don't load all apps excessively + const isBuilderPreview = ctx.path.startsWith(BUILDER_PREVIEW_PATH) + const isViewingProdApp = + ctx.path.startsWith(PROD_APP_PREFIX) && !isBuilderPreview + if (!appId && isViewingProdApp) { appId = confirmAppId(await resolveAppUrl(ctx)) } + // look in the referer - builder only + // make sure this is performed after prod app url resolution, in case the + // referer header is present from a builder redirect + const referer = ctx.request.headers.referer + if (!appId && referer?.includes(BUILDER_REFERER_PREFIX)) { + const refererId = parseAppIdFromUrl(ctx.request.headers.referer) + appId = confirmAppId(refererId) + } + return appId } +function parseAppIdFromUrl(url?: string) { + if (!url) { + return + } + return url.split("/").find(subPath => subPath.startsWith(APP_PREFIX)) +} + /** * opens the contents of the specified encrypted JWT. * @return {object} the contents of the token. @@ -115,7 +143,7 @@ export function openJwt(token: string) { * @param {object} ctx The request which is to be manipulated. * @param {string} name The name of the cookie to get. */ -export function getCookie(ctx: BBContext, name: string) { +export function getCookie(ctx: Ctx, name: string) { const cookie = ctx.cookies.get(name) if (!cookie) { @@ -133,7 +161,7 @@ export function getCookie(ctx: BBContext, name: string) { * @param {object} opts options like whether to sign. */ export function setCookie( - ctx: BBContext, + ctx: Ctx, value: any, name = "builder", opts = { sign: true } @@ -159,7 +187,7 @@ export function setCookie( /** * Utility function, simply calls setCookie with an empty string for value */ -export function clearCookie(ctx: BBContext, name: string) { +export function clearCookie(ctx: Ctx, name: string) { setCookie(ctx, null, name) } @@ -169,7 +197,7 @@ export function clearCookie(ctx: BBContext, name: string) { * @param {object} ctx The koa context object to be tested. * @return {boolean} returns true if the call is from the client lib (a built app rather than the builder). */ -export function isClient(ctx: BBContext) { +export function isClient(ctx: Ctx) { return ctx.headers[Header.TYPE] === "client" } diff --git a/packages/backend-core/tests/jestSetup.ts b/packages/backend-core/tests/jestSetup.ts index 7870a721aa..b7ab5b49d9 100644 --- a/packages/backend-core/tests/jestSetup.ts +++ b/packages/backend-core/tests/jestSetup.ts @@ -17,7 +17,9 @@ env._set("MINIO_URL", "http://localhost") env._set("MINIO_ACCESS_KEY", "test") env._set("MINIO_SECRET_KEY", "test") -global.console.log = jest.fn() // console.log are ignored in tests +if (!process.env.DEBUG) { + global.console.log = jest.fn() // console.log are ignored in tests +} if (!process.env.CI) { // set a longer timeout in dev for debugging diff --git a/packages/backend-core/tests/utilities/index.ts b/packages/backend-core/tests/utilities/index.ts index 65578ff013..ee96a94152 100644 --- a/packages/backend-core/tests/utilities/index.ts +++ b/packages/backend-core/tests/utilities/index.ts @@ -1,6 +1,7 @@ export * as mocks from "./mocks" export * as structures from "./structures" export { generator } from "./structures" +export * as testEnv from "./testEnv" import * as dbConfig from "./db" dbConfig.init() diff --git a/packages/backend-core/tests/utilities/mocks/accounts.ts b/packages/backend-core/tests/utilities/mocks/accounts.ts index cb4c68b65e..e40d32b276 100644 --- a/packages/backend-core/tests/utilities/mocks/accounts.ts +++ b/packages/backend-core/tests/utilities/mocks/accounts.ts @@ -1,9 +1,13 @@ -export const getAccount = jest.fn() -export const getAccountByTenantId = jest.fn() -export const getStatus = jest.fn() +const mockGetAccount = jest.fn() +const mockGetAccountByTenantId = jest.fn() +const mockGetStatus = jest.fn() jest.mock("../../../src/cloud/accounts", () => ({ - getAccount, - getAccountByTenantId, - getStatus, + getAccount: mockGetAccount, + getAccountByTenantId: mockGetAccountByTenantId, + getStatus: mockGetStatus, })) + +export const getAccount = mockGetAccount +export const getAccountByTenantId = mockGetAccountByTenantId +export const getStatus = mockGetStatus diff --git a/packages/backend-core/tests/utilities/mocks/events.ts b/packages/backend-core/tests/utilities/mocks/events.ts index 415d59019d..ab0aaa93a6 100644 --- a/packages/backend-core/tests/utilities/mocks/events.ts +++ b/packages/backend-core/tests/utilities/mocks/events.ts @@ -1,9 +1,8 @@ -const processors = require("../../../src/events/processors") +import * as processors from "../../../src/events/processors" +import * as events from "../../../src/events" jest.spyOn(processors.analyticsProcessor, "processEvent") -const events = require("../../../src/events") - jest.spyOn(events.identification, "identifyTenantGroup") jest.spyOn(events.identification, "identifyUser") @@ -117,3 +116,7 @@ jest.spyOn(events.view, "filterDeleted") jest.spyOn(events.view, "calculationCreated") jest.spyOn(events.view, "calculationUpdated") jest.spyOn(events.view, "calculationDeleted") + +jest.spyOn(events.plugin, "init") +jest.spyOn(events.plugin, "imported") +jest.spyOn(events.plugin, "deleted") diff --git a/packages/backend-core/tests/utilities/mocks/index.ts b/packages/backend-core/tests/utilities/mocks/index.ts index e71c739e26..401fd7d7a7 100644 --- a/packages/backend-core/tests/utilities/mocks/index.ts +++ b/packages/backend-core/tests/utilities/mocks/index.ts @@ -1,5 +1,6 @@ -import "./posthog" -import "./events" export * as accounts from "./accounts" export * as date from "./date" +export * as licenses from "./licenses" export { default as fetch } from "./fetch" +import "./posthog" +import "./events" diff --git a/packages/backend-core/tests/utilities/mocks/licenses.ts b/packages/backend-core/tests/utilities/mocks/licenses.ts new file mode 100644 index 0000000000..1fbda5655e --- /dev/null +++ b/packages/backend-core/tests/utilities/mocks/licenses.ts @@ -0,0 +1,83 @@ +import { Feature, License, Quotas } from "@budibase/types" +import _ from "lodash" + +let CLOUD_FREE_LICENSE: License +let UNLIMITED_LICENSE: License +let getCachedLicense: any + +// init for the packages other than pro +export function init(proPkg: any) { + initInternal({ + CLOUD_FREE_LICENSE: proPkg.constants.licenses.CLOUD_FREE_LICENSE, + UNLIMITED_LICENSE: proPkg.constants.licenses.UNLIMITED_LICENSE, + getCachedLicense: proPkg.licensing.cache.getCachedLicense, + }) +} + +// init for the pro package +export function initInternal(opts: { + CLOUD_FREE_LICENSE: License + UNLIMITED_LICENSE: License + getCachedLicense: any +}) { + CLOUD_FREE_LICENSE = opts.CLOUD_FREE_LICENSE + UNLIMITED_LICENSE = opts.UNLIMITED_LICENSE + getCachedLicense = opts.getCachedLicense +} + +export interface UseLicenseOpts { + features?: Feature[] + quotas?: Quotas +} + +// LICENSES + +export const useLicense = (license: License, opts?: UseLicenseOpts) => { + if (opts) { + if (opts.features) { + license.features.push(...opts.features) + } + if (opts.quotas) { + license.quotas = opts.quotas + } + } + + getCachedLicense.mockReturnValue(license) + + return license +} + +export const useUnlimited = (opts?: UseLicenseOpts) => { + return useLicense(UNLIMITED_LICENSE, opts) +} + +export const useCloudFree = () => { + return useLicense(CLOUD_FREE_LICENSE) +} + +// FEATURES + +const useFeature = (feature: Feature) => { + const license = _.cloneDeep(UNLIMITED_LICENSE) + const opts: UseLicenseOpts = { + features: [feature], + } + + return useLicense(license, opts) +} + +export const useBackups = () => { + return useFeature(Feature.APP_BACKUPS) +} + +export const useGroups = () => { + return useFeature(Feature.USER_GROUPS) +} + +// QUOTAS + +export const setAutomationLogsQuota = (value: number) => { + const license = _.cloneDeep(UNLIMITED_LICENSE) + license.quotas.constant.automationLogRetentionDays.value = value + return useLicense(license) +} diff --git a/packages/backend-core/tests/utilities/structures/apps.ts b/packages/backend-core/tests/utilities/structures/apps.ts new file mode 100644 index 0000000000..f3743d99b2 --- /dev/null +++ b/packages/backend-core/tests/utilities/structures/apps.ts @@ -0,0 +1,21 @@ +import { generator } from "." +import { App } from "@budibase/types" +import { DEFAULT_TENANT_ID, DocumentType } from "../../../src/constants" + +export function app(id: string): App { + return { + _id: DocumentType.APP_METADATA, + appId: id, + type: "", + version: "0.0.1", + componentLibraries: [], + name: generator.name(), + url: `/custom-url`, + instance: { + _id: id, + }, + tenantId: DEFAULT_TENANT_ID, + status: "", + template: undefined, + } +} diff --git a/packages/backend-core/tests/utilities/structures/index.ts b/packages/backend-core/tests/utilities/structures/index.ts index 68064b9715..0d0f0c507f 100644 --- a/packages/backend-core/tests/utilities/structures/index.ts +++ b/packages/backend-core/tests/utilities/structures/index.ts @@ -3,6 +3,8 @@ export * from "./common" import Chance from "chance" export const generator = new Chance() -export * as koa from "./koa" export * as accounts from "./accounts" +export * as apps from "./apps" +export * as koa from "./koa" export * as licenses from "./licenses" +export * as plugins from "./plugins" diff --git a/packages/backend-core/tests/utilities/structures/koa.ts b/packages/backend-core/tests/utilities/structures/koa.ts index a33dca1546..102fe029de 100644 --- a/packages/backend-core/tests/utilities/structures/koa.ts +++ b/packages/backend-core/tests/utilities/structures/koa.ts @@ -5,9 +5,11 @@ export const newContext = (): BBContext => { const ctx = createMockContext() return { ...ctx, + path: "/", cookies: createMockCookies(), request: { ...ctx.request, + headers: {}, body: {}, }, } diff --git a/packages/backend-core/tests/utilities/structures/plugins.ts b/packages/backend-core/tests/utilities/structures/plugins.ts new file mode 100644 index 0000000000..e2d92858d3 --- /dev/null +++ b/packages/backend-core/tests/utilities/structures/plugins.ts @@ -0,0 +1,19 @@ +import { generator } from "." +import { Plugin, PluginSource, PluginType } from "@budibase/types" + +export function plugin(): Plugin { + return { + description: generator.word(), + name: generator.word(), + version: "1.0.0", + source: PluginSource.FILE, + package: { + name: generator.word, + }, + hash: generator.hash(), + schema: { + type: PluginType.DATASOURCE, + }, + iconFileName: "icon.svg", + } +} diff --git a/packages/backend-core/tests/utilities/testEnv.ts b/packages/backend-core/tests/utilities/testEnv.ts new file mode 100644 index 0000000000..b4f06b5153 --- /dev/null +++ b/packages/backend-core/tests/utilities/testEnv.ts @@ -0,0 +1,87 @@ +import env from "../../src/environment" +import * as tenancy from "../../src/tenancy" +import { newid } from "../../src/utils" + +// TENANCY + +export async function withTenant(task: (tenantId: string) => any) { + const tenantId = newid() + return tenancy.doInTenant(tenantId, async () => { + await task(tenantId) + }) +} + +export function singleTenant() { + env._set("MULTI_TENANCY", 0) +} + +export function multiTenant() { + env._set("MULTI_TENANCY", 1) +} + +// NODE + +export function nodeDev() { + env._set("NODE_ENV", "dev") +} + +export function nodeJest() { + env._set("NODE_ENV", "jest") +} + +// FILES + +export function withS3() { + env._set("NODE_ENV", "production") + env._set("MINIO_ENABLED", 0) + env._set("MINIO_URL", "http://s3.example.com") + env._set("CLOUDFRONT_CDN", undefined) +} + +const CLOUDFRONT_TEST_KEY = + "-----BEGIN RSA PRIVATE KEY-----\n" + + "MIIEpAIBAAKCAQEAqXRsir/0Qba1xEnybUs7d7QEAE02GRc+4H7HD5l5VnAxkV1m\n" + + "tNTXTmoYkaIhLdebV1EwQs3T9knxoyd4cVcrDkDfDLZErfYWJsuE3/QYNknnZs4/\n" + + "Ai0cg+v9ZX3gcizvpYg9GQI3INM0uRG8lJwGP7FQ/kknhA2yVFVCSxX6kkNtOUh5\n" + + "dKSG7m6IwswcSwD++Z/94vsFkoZIGY0e1CD/drFJ6+1TFY2YgbDKT5wDFLJ9vHFx\n" + + "/5o4POwn3gz/ru2Db9jbRdfEAqRdy46nRKQgBGUmupAgSK1+BJEzafexp8RmCGb0\n" + + "WUffxOtj8/jNCeCF0JBgVHAe3crOQ8ySrtoaHQIDAQABAoIBAA+ipW07/u6dTDI7\n" + + "XHoHKgqGeqQIe8he47dVG0ruL0rxeTFfe92NkfwzP+cYHZWcQkIRRLG1Six8cCZM\n" + + "uwlCML/U7n++xaGDhlG4D5+WZzGDKi3LM/cgcHQfrzbRIYeHa+lLI9AN60ZFFqVI\n" + + "5KyVpOH1m3KLD3FYzi6H22EQOxmJpqWlt2uArny5LxlPJKmmGSFjvneb4N2ZAKGQ\n" + + "QfClJGz9tRjceWUUdJrpqmTmBQIosKmLPq8PEviUNAVG+6m4r8jiRbf8OKkAm+3L\n" + + "LVIsN8HfYB9jEuERYPnbuXdX0kDEkg0xEyTH5YbNZvfm5ptCU9Xn+Jz1trF+wCHD\n" + + "2RlxdQUCgYEA3U0nCf6NTmmeMCsAX6gvaPuM0iUfUfS3b3G57I6u46lLGNLsfJw6\n" + + "MTpVc164lKYQK9czw/ijKzb8e3mcyzbPorVkajMjUCNWGrMK+vFbOGmqQkhUi30U\n" + + "IJuuTktMd+21D/SpLlev4MLria23vUIKEqNenYpV6wkGLt/mKtISaPMCgYEAxAYx\n" + + "j+xJLTK9eN+rpekwjYE78hD9VoBkBnr/NBiGV302AsJRuq2+L4zcBnAsH+SidFim\n" + + "cwqoj3jeVT8ZQFXlK3fGVaEJsCXd6GWk8ZIWUTn9JZwi2KcCvCU/YiHfx8c7y7Gl\n" + + "SiPXUPsvvkcw6RRh2u4J5tHLIqJe3W58ENoBNK8CgYEApxTBDMKrXTBQxn0w4wfQ\n" + + "A6soPuDYLMBeXj226eswD6KZmDxnYA1zwgcQzPIO2ewm+XKZGrR2PQJezbqbrrHL\n" + + "QkVBcwz49GA5eh8Dg0MGZCki6rhBXK8qqxPfHi2rpkBKG6nUsbBykXeY7XHC75kU\n" + + "kc3WeYsgIzvE908EMAA69hECgYEAinbpiYVZh1DBH+G26MIYZswz4OB5YyHcBevZ\n" + + "2x27v48VmMtUWe4iWopAXVfdA0ZILrD0Gm0b9gRl4IdqudQyxgqcEZ5oLoIBBwjN\n" + + "g0oy83tnwqpQvwLx3p7c79+HqCGmrlK0s/MvQ+e6qMi21t1r5e6hFed5euSA6B8E\n" + + "Cg9ELMcCgYB9bGwlNAE+iuzMIhKev1s7h3TzqKtGw37TtHXvxcTQs3uawJQksQ2s\n" + + "K0Zy1Ta7vybbwAA5m+LxoMT04WUdJO7Cr8/3rBMrbKKO3H7IgC3G+nXnOBdshzn5\n" + + "ifMbhZslFThC/osD5ZV7snXZgTWyPexaINJhHmdrAWpmW1h+UFoiMw==\n" + + "-----END RSA PRIVATE KEY-----\n" + +const CLOUDFRONT_TEST_KEY_64 = Buffer.from( + CLOUDFRONT_TEST_KEY, + "utf-8" +).toString("base64") + +export function withCloudfront() { + withS3() + env._set("CLOUDFRONT_CDN", "http://cf.example.com") + env._set("CLOUDFRONT_PUBLIC_KEY_ID", "keypair_123") + env._set("CLOUDFRONT_PRIVATE_KEY_64", CLOUDFRONT_TEST_KEY_64) +} + +export function withMinio() { + env._set("NODE_ENV", "production") + env._set("MINIO_ENABLED", 1) + env._set("MINIO_URL", "http://minio.example.com") + env._set("CLOUDFRONT_CDN", undefined) +} diff --git a/packages/backend-core/tsconfig.build.json b/packages/backend-core/tsconfig.build.json index 9682f3e32f..12f8255a7c 100644 --- a/packages/backend-core/tsconfig.build.json +++ b/packages/backend-core/tsconfig.build.json @@ -12,6 +12,7 @@ "declaration": true, "types": [ "node", "jest" ], "outDir": "dist", + "skipLibCheck": true }, "include": [ "**/*.js", @@ -22,6 +23,7 @@ "node_modules", "dist", "**/*.spec.ts", - "**/*.spec.js" + "**/*.spec.js", + "__mocks__" ] } \ No newline at end of file diff --git a/packages/backend-core/tsconfig.json b/packages/backend-core/tsconfig.json index ccefd149a0..e95fb9ab4d 100644 --- a/packages/backend-core/tsconfig.json +++ b/packages/backend-core/tsconfig.json @@ -8,6 +8,10 @@ } }, "references": [ - { "path": "../types" }, + { "path": "../types" } + ], + "exclude": [ + "node_modules", + "dist", ] } \ No newline at end of file diff --git a/packages/backend-core/yarn.lock b/packages/backend-core/yarn.lock index 16de2cbaf8..03393a4ea8 100644 --- a/packages/backend-core/yarn.lock +++ b/packages/backend-core/yarn.lock @@ -10,128 +10,64 @@ "@jridgewell/gen-mapping" "^0.1.0" "@jridgewell/trace-mapping" "^0.3.9" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" - integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== - dependencies: - "@babel/highlight" "^7.16.7" - -"@babel/code-frame@^7.18.6": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== dependencies: "@babel/highlight" "^7.18.6" -"@babel/compat-data@^7.17.10": - version "7.17.10" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.17.10.tgz#711dc726a492dfc8be8220028b1b92482362baab" - integrity sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw== +"@babel/compat-data@^7.20.5": + version "7.20.10" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.10.tgz#9d92fa81b87542fff50e848ed585b4212c1d34ec" + integrity sha512-sEnuDPpOJR/fcafHMjpcpGN5M2jbUGUHwmuWKM/YdPzeEDJg8bgmbcWQFUfE32MQjti1koACvoPVsDe8Uq+idg== -"@babel/compat-data@^7.20.0": - version "7.20.1" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.1.tgz#f2e6ef7790d8c8dbf03d379502dcc246dcce0b30" - integrity sha512-EWZ4mE2diW3QALKvDMiXnbZpRvlj+nayZ112nK93SnhqOtpdsbVD4W+2tEoT3YNBAG9RBR0ISY758ZkOgsn6pQ== - -"@babel/core@^7.11.6": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.20.2.tgz#8dc9b1620a673f92d3624bd926dc49a52cf25b92" - integrity sha512-w7DbG8DtMrJcFOi4VrLm+8QM4az8Mo+PuLBKLp2zrYRCow8W/f9xiXm5sN53C8HksCyDQwCKha9JiDoIyPjT2g== +"@babel/core@^7.11.6", "@babel/core@^7.12.3": + version "7.20.12" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.20.12.tgz#7930db57443c6714ad216953d1356dac0eb8496d" + integrity sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg== dependencies: "@ampproject/remapping" "^2.1.0" "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.20.2" - "@babel/helper-compilation-targets" "^7.20.0" - "@babel/helper-module-transforms" "^7.20.2" - "@babel/helpers" "^7.20.1" - "@babel/parser" "^7.20.2" - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.20.1" - "@babel/types" "^7.20.2" + "@babel/generator" "^7.20.7" + "@babel/helper-compilation-targets" "^7.20.7" + "@babel/helper-module-transforms" "^7.20.11" + "@babel/helpers" "^7.20.7" + "@babel/parser" "^7.20.7" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.20.12" + "@babel/types" "^7.20.7" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" - json5 "^2.2.1" + json5 "^2.2.2" semver "^6.3.0" -"@babel/core@^7.12.3": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.18.2.tgz#87b2fcd7cce9becaa7f5acebdc4f09f3dd19d876" - integrity sha512-A8pri1YJiC5UnkdrWcmfZTJTV85b4UXTAfImGmCfYmax4TR9Cw8sDS0MOk++Gp2mE/BefVJ5nwy5yzqNJbP/DQ== +"@babel/generator@^7.20.7", "@babel/generator@^7.7.2": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.7.tgz#f8ef57c8242665c5929fe2e8d82ba75460187b4a" + integrity sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw== dependencies: - "@ampproject/remapping" "^2.1.0" - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.18.2" - "@babel/helper-compilation-targets" "^7.18.2" - "@babel/helper-module-transforms" "^7.18.0" - "@babel/helpers" "^7.18.2" - "@babel/parser" "^7.18.0" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.18.2" - "@babel/types" "^7.18.2" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.1" - semver "^6.3.0" - -"@babel/generator@^7.18.2", "@babel/generator@^7.7.2": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.18.2.tgz#33873d6f89b21efe2da63fe554460f3df1c5880d" - integrity sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw== - dependencies: - "@babel/types" "^7.18.2" - "@jridgewell/gen-mapping" "^0.3.0" - jsesc "^2.5.1" - -"@babel/generator@^7.20.1", "@babel/generator@^7.20.2": - version "7.20.4" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.4.tgz#4d9f8f0c30be75fd90a0562099a26e5839602ab8" - integrity sha512-luCf7yk/cm7yab6CAW1aiFnmEfBJplb/JojV56MYEK7ziWfGmFlTfmL9Ehwfy4gFhbjBfWO1wj7/TuSbVNEEtA== - dependencies: - "@babel/types" "^7.20.2" + "@babel/types" "^7.20.7" "@jridgewell/gen-mapping" "^0.3.2" jsesc "^2.5.1" -"@babel/helper-compilation-targets@^7.18.2": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.2.tgz#67a85a10cbd5fc7f1457fec2e7f45441dc6c754b" - integrity sha512-s1jnPotJS9uQnzFtiZVBUxe67CuBa679oWFHpxYYnTpRL/1ffhyX44R9uYiXoa/pLXcY9H2moJta0iaanlk/rQ== +"@babel/helper-compilation-targets@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz#a6cd33e93629f5eb473b021aac05df62c4cd09bb" + integrity sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ== dependencies: - "@babel/compat-data" "^7.17.10" - "@babel/helper-validator-option" "^7.16.7" - browserslist "^4.20.2" - semver "^6.3.0" - -"@babel/helper-compilation-targets@^7.20.0": - version "7.20.0" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.0.tgz#6bf5374d424e1b3922822f1d9bdaa43b1a139d0a" - integrity sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ== - dependencies: - "@babel/compat-data" "^7.20.0" + "@babel/compat-data" "^7.20.5" "@babel/helper-validator-option" "^7.18.6" browserslist "^4.21.3" + lru-cache "^5.1.1" semver "^6.3.0" -"@babel/helper-environment-visitor@^7.16.7", "@babel/helper-environment-visitor@^7.18.2": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.2.tgz#8a6d2dedb53f6bf248e31b4baf38739ee4a637bd" - integrity sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ== - "@babel/helper-environment-visitor@^7.18.9": version "7.18.9" resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== -"@babel/helper-function-name@^7.17.9": - version "7.17.9" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz#136fcd54bc1da82fcb47565cf16fd8e444b1ff12" - integrity sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg== - dependencies: - "@babel/template" "^7.16.7" - "@babel/types" "^7.17.0" - "@babel/helper-function-name@^7.19.0": version "7.19.0" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c" @@ -140,13 +76,6 @@ "@babel/template" "^7.18.10" "@babel/types" "^7.19.0" -"@babel/helper-hoist-variables@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246" - integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg== - dependencies: - "@babel/types" "^7.16.7" - "@babel/helper-hoist-variables@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" @@ -154,13 +83,6 @@ dependencies: "@babel/types" "^7.18.6" -"@babel/helper-module-imports@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437" - integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg== - dependencies: - "@babel/types" "^7.16.7" - "@babel/helper-module-imports@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" @@ -168,45 +90,24 @@ dependencies: "@babel/types" "^7.18.6" -"@babel/helper-module-transforms@^7.18.0": - version "7.18.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.18.0.tgz#baf05dec7a5875fb9235bd34ca18bad4e21221cd" - integrity sha512-kclUYSUBIjlvnzN2++K9f2qzYKFgjmnmjwL4zlmU5f8ZtzgWe8s0rUPSTGy2HmK4P8T52MQsS+HTQAgZd3dMEA== - dependencies: - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-module-imports" "^7.16.7" - "@babel/helper-simple-access" "^7.17.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/helper-validator-identifier" "^7.16.7" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.18.0" - "@babel/types" "^7.18.0" - -"@babel/helper-module-transforms@^7.20.2": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.20.2.tgz#ac53da669501edd37e658602a21ba14c08748712" - integrity sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA== +"@babel/helper-module-transforms@^7.20.11": + version "7.20.11" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz#df4c7af713c557938c50ea3ad0117a7944b2f1b0" + integrity sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg== dependencies: "@babel/helper-environment-visitor" "^7.18.9" "@babel/helper-module-imports" "^7.18.6" "@babel/helper-simple-access" "^7.20.2" "@babel/helper-split-export-declaration" "^7.18.6" "@babel/helper-validator-identifier" "^7.19.1" - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.20.1" - "@babel/types" "^7.20.2" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.20.10" + "@babel/types" "^7.20.7" -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.17.12", "@babel/helper-plugin-utils@^7.8.0": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.17.12.tgz#86c2347da5acbf5583ba0a10aed4c9bf9da9cf96" - integrity sha512-JDkf04mqtN3y4iAbO1hv9U2ARpPyPL1zqyWs/2WG1pgSq9llHFjStX5jdxb84himgJm+8Ng+x0oiWF/nw/XQKA== - -"@babel/helper-simple-access@^7.17.7": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.18.2.tgz#4dc473c2169ac3a1c9f4a51cfcd091d1c36fcff9" - integrity sha512-7LIrjYzndorDY88MycupkpQLKS1AFfsVRm2k/9PtKScSy5tZq0McZTj+DiMRynboZfIqOKvo03pmhTaUgiD6fQ== - dependencies: - "@babel/types" "^7.18.2" +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.8.0": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz#d1b9000752b18d0877cff85a5c376ce5c3121629" + integrity sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ== "@babel/helper-simple-access@^7.20.2": version "7.20.2" @@ -215,13 +116,6 @@ dependencies: "@babel/types" "^7.20.2" -"@babel/helper-split-export-declaration@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b" - integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw== - dependencies: - "@babel/types" "^7.16.7" - "@babel/helper-split-export-declaration@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" @@ -234,52 +128,24 @@ resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63" integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw== -"@babel/helper-validator-identifier@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" - integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== - "@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": version "7.19.1" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== -"@babel/helper-validator-option@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23" - integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ== - "@babel/helper-validator-option@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== -"@babel/helpers@^7.18.2": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.18.2.tgz#970d74f0deadc3f5a938bfa250738eb4ac889384" - integrity sha512-j+d+u5xT5utcQSzrh9p+PaJX94h++KN+ng9b9WEJq7pkUPAd61FGqhjuUEdfknb3E/uDBb7ruwEeKkIxNJPIrg== +"@babel/helpers@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.20.7.tgz#04502ff0feecc9f20ecfaad120a18f011a8e6dce" + integrity sha512-PBPjs5BppzsGaxHQCDKnZ6Gd9s6xl8bBCluz3vEInLGRJmnZan4F6BYCeqtyXqkk4W5IlPmjK4JlOuZkpJ3xZA== dependencies: - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.18.2" - "@babel/types" "^7.18.2" - -"@babel/helpers@^7.20.1": - version "7.20.1" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.20.1.tgz#2ab7a0fcb0a03b5bf76629196ed63c2d7311f4c9" - integrity sha512-J77mUVaDTUJFZ5BpP6mMn6OIl3rEWymk2ZxDBQJUG3P+PbmyMcF3bYWvz0ma69Af1oobDqT/iAsvzhB58xhQUg== - dependencies: - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.20.1" - "@babel/types" "^7.20.0" - -"@babel/highlight@^7.16.7": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.17.12.tgz#257de56ee5afbd20451ac0a75686b6b404257351" - integrity sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg== - dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - chalk "^2.0.0" - js-tokens "^4.0.0" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.20.7" + "@babel/types" "^7.20.7" "@babel/highlight@^7.18.6": version "7.18.6" @@ -290,15 +156,10 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.16.7", "@babel/parser@^7.18.0": - version "7.18.4" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.4.tgz#6774231779dd700e0af29f6ad8d479582d7ce5ef" - integrity sha512-FDge0dFazETFcxGw/EXzOkN8uJp0PC7Qbm+Pe9T+av2zlBpOgunFHkQPPn+eRuClU73JF+98D531UgayY89tow== - -"@babel/parser@^7.18.10", "@babel/parser@^7.20.1", "@babel/parser@^7.20.2": - version "7.20.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.3.tgz#5358cf62e380cf69efcb87a7bb922ff88bfac6e2" - integrity sha512-OP/s5a94frIPXwjzEcv5S/tpQfc6XhxYUnmWpgdqMWGgYCuErA3SzozaRAMQgSZWKeTJxht9aWAkUY+0UzvOFg== +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.7.tgz#66fe23b3c8569220817d5feb8b9dcdc95bb4f71b" + integrity sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg== "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" @@ -385,81 +246,48 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-typescript@^7.7.2": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.17.12.tgz#b54fc3be6de734a56b87508f99d6428b5b605a7b" - integrity sha512-TYY0SXFiO31YXtNg3HtFwNJHjLsAyIIhAhNWkQ5whPPS7HWUFlg9z0Ta4qAQNjQbP1wsSt/oKkmZ/4/WWdMUpw== + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz#4e9a0cfc769c85689b77a2e642d24e9f697fc8c7" + integrity sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ== dependencies: - "@babel/helper-plugin-utils" "^7.17.12" + "@babel/helper-plugin-utils" "^7.19.0" "@babel/runtime@^7.15.4": - version "7.18.3" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.3.tgz#c7b654b57f6f63cf7f8b418ac9ca04408c4579f4" - integrity sha512-38Y8f7YUhce/K7RMwTp7m0uCumpv9hZkitCbBClqQIow1qSbCvGkcegKOXpEWCQLfWmevgRiWokZ1GkpfhbZug== + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.7.tgz#fcb41a5a70550e04a7b708037c7c32f7f356d8fd" + integrity sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ== dependencies: - regenerator-runtime "^0.13.4" + regenerator-runtime "^0.13.11" -"@babel/template@^7.16.7", "@babel/template@^7.3.3": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" - integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/parser" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/template@^7.18.10": - version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71" - integrity sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA== +"@babel/template@^7.18.10", "@babel/template@^7.20.7", "@babel/template@^7.3.3": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.20.7.tgz#a15090c2839a83b02aa996c0b4994005841fd5a8" + integrity sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw== dependencies: "@babel/code-frame" "^7.18.6" - "@babel/parser" "^7.18.10" - "@babel/types" "^7.18.10" + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" -"@babel/traverse@^7.18.0", "@babel/traverse@^7.18.2", "@babel/traverse@^7.7.2": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.18.2.tgz#b77a52604b5cc836a9e1e08dca01cba67a12d2e8" - integrity sha512-9eNwoeovJ6KH9zcCNnENY7DMFwTU9JdGCFtqNLfUAqtUHRCOsTOqWoffosP8vKmNYeSBUv3yVJXjfd8ucwOjUA== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.18.2" - "@babel/helper-environment-visitor" "^7.18.2" - "@babel/helper-function-name" "^7.17.9" - "@babel/helper-hoist-variables" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/parser" "^7.18.0" - "@babel/types" "^7.18.2" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/traverse@^7.20.1": - version "7.20.1" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.1.tgz#9b15ccbf882f6d107eeeecf263fbcdd208777ec8" - integrity sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA== +"@babel/traverse@^7.20.10", "@babel/traverse@^7.20.12", "@babel/traverse@^7.20.7", "@babel/traverse@^7.7.2": + version "7.20.12" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.12.tgz#7f0f787b3a67ca4475adef1f56cb94f6abd4a4b5" + integrity sha512-MsIbFN0u+raeja38qboyF8TIT7K0BFzz/Yd/77ta4MsUsmP2RAnidIlwq7d5HFQrH/OZJecGV6B71C4zAgpoSQ== dependencies: "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.20.1" + "@babel/generator" "^7.20.7" "@babel/helper-environment-visitor" "^7.18.9" "@babel/helper-function-name" "^7.19.0" "@babel/helper-hoist-variables" "^7.18.6" "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/parser" "^7.20.1" - "@babel/types" "^7.20.0" + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.16.7", "@babel/types@^7.17.0", "@babel/types@^7.18.0", "@babel/types@^7.18.2", "@babel/types@^7.3.0", "@babel/types@^7.3.3": - version "7.18.4" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.18.4.tgz#27eae9b9fd18e9dccc3f9d6ad051336f307be354" - integrity sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw== - dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - to-fast-properties "^2.0.0" - -"@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.19.0", "@babel/types@^7.20.0", "@babel/types@^7.20.2": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.20.2.tgz#67ac09266606190f496322dbaff360fdaa5e7842" - integrity sha512-FnnvsNWgZCr232sqtXggapvlkk/tuwR/qhGzcmxI0GXLCjmPYQPzio2FbdlWuY6y1sHFfQKk+rRbUZ9VStQMog== +"@babel/types@^7.0.0", "@babel/types@^7.18.6", "@babel/types@^7.19.0", "@babel/types@^7.20.2", "@babel/types@^7.20.7", "@babel/types@^7.3.0", "@babel/types@^7.3.3": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.20.7.tgz#54ec75e252318423fc07fb644dc6a58a64c09b7f" + integrity sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg== dependencies: "@babel/helper-string-parser" "^7.19.4" "@babel/helper-validator-identifier" "^7.19.1" @@ -564,6 +392,13 @@ slash "^3.0.0" strip-ansi "^6.0.0" +"@jest/create-cache-key-function@^27.4.2": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/create-cache-key-function/-/create-cache-key-function-27.5.1.tgz#7448fae15602ea95c828f5eceed35c202a820b31" + integrity sha512-dmH1yW+makpTSURTy8VzdUwFnfQh1G8R+DxO2Ho2FFmBbKFEVm+3jWdvFhE2VqB/LATCTokkP0dotjyQyw5/AQ== + dependencies: + "@jest/types" "^27.5.1" + "@jest/environment@^28.1.3": version "28.1.3" resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-28.1.3.tgz#abed43a6b040a4c24fdcb69eab1f97589b2d663e" @@ -698,6 +533,17 @@ slash "^3.0.0" write-file-atomic "^4.0.1" +"@jest/types@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.5.1.tgz#3c79ec4a8ba61c170bf937bcf9e98a9df175ec80" + integrity sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^16.0.0" + chalk "^4.0.0" + "@jest/types@^28.1.1", "@jest/types@^28.1.3": version "28.1.3" resolved "https://registry.yarnpkg.com/@jest/types/-/types-28.1.3.tgz#b05de80996ff12512bc5ceb1d208285a7d11748b" @@ -718,15 +564,6 @@ "@jridgewell/set-array" "^1.0.0" "@jridgewell/sourcemap-codec" "^1.4.10" -"@jridgewell/gen-mapping@^0.3.0": - version "0.3.1" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz#cf92a983c83466b8c0ce9124fadeaf09f7c66ea9" - integrity sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg== - dependencies: - "@jridgewell/set-array" "^1.0.0" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.9" - "@jridgewell/gen-mapping@^0.3.2": version "0.3.2" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" @@ -736,36 +573,21 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/resolve-uri@3.1.0": +"@jridgewell/resolve-uri@3.1.0", "@jridgewell/resolve-uri@^3.0.3": version "3.1.0" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== -"@jridgewell/resolve-uri@^3.0.3": - version "3.0.7" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz#30cd49820a962aff48c8fffc5cd760151fca61fe" - integrity sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA== - -"@jridgewell/set-array@^1.0.0": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.1.tgz#36a6acc93987adcf0ba50c66908bd0b70de8afea" - integrity sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ== - -"@jridgewell/set-array@^1.0.1": +"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": version "1.1.2" resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== -"@jridgewell/sourcemap-codec@1.4.14": +"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": version "1.4.14" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== -"@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.13" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz#b6461fb0c2964356c469e115f504c95ad97ab88c" - integrity sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w== - "@jridgewell/trace-mapping@0.3.9": version "0.3.9" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" @@ -774,7 +596,7 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" -"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.13": +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.13", "@jridgewell/trace-mapping@^0.3.9": version "0.3.17" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== @@ -782,18 +604,10 @@ "@jridgewell/resolve-uri" "3.1.0" "@jridgewell/sourcemap-codec" "1.4.14" -"@jridgewell/trace-mapping@^0.3.9": - version "0.3.13" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz#dcfe3e95f224c8fe97a87a5235defec999aa92ea" - integrity sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@mapbox/node-pre-gyp@^1.0.0": - version "1.0.9" - resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz#09a8781a3a036151cdebbe8719d6f8b25d4058bc" - integrity sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw== + version "1.0.10" + resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz#8e6735ccebbb1581e5a7e652244cadc8a844d03c" + integrity sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA== dependencies: detect-libc "^2.0.0" https-proxy-agent "^5.0.0" @@ -805,35 +619,35 @@ semver "^7.3.5" tar "^6.1.11" -"@msgpackr-extract/msgpackr-extract-darwin-arm64@2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-2.1.2.tgz#9571b87be3a3f2c46de05585470bc4f3af2f6f00" - integrity sha512-TyVLn3S/+ikMDsh0gbKv2YydKClN8HaJDDpONlaZR+LVJmsxLFUgA+O7zu59h9+f9gX1aj/ahw9wqa6rosmrYQ== +"@msgpackr-extract/msgpackr-extract-darwin-arm64@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-2.2.0.tgz#901c5937e1441572ea23e631fe6deca68482fe76" + integrity sha512-Z9LFPzfoJi4mflGWV+rv7o7ZbMU5oAU9VmzCgL240KnqDW65Y2HFCT3MW06/ITJSnbVLacmcEJA8phywK7JinQ== -"@msgpackr-extract/msgpackr-extract-darwin-x64@2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-2.1.2.tgz#bfbc6936ede2955218f5621a675679a5fe8e6f4c" - integrity sha512-YPXtcVkhmVNoMGlqp81ZHW4dMxK09msWgnxtsDpSiZwTzUBG2N+No2bsr7WMtBKCVJMSD6mbAl7YhKUqkp/Few== +"@msgpackr-extract/msgpackr-extract-darwin-x64@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-2.2.0.tgz#fb877fe6bae3c4d3cea29786737840e2ae689066" + integrity sha512-vq0tT8sjZsy4JdSqmadWVw6f66UXqUCabLmUVHZwUFzMgtgoIIQjT4VVRHKvlof3P/dMCkbMJ5hB1oJ9OWHaaw== -"@msgpackr-extract/msgpackr-extract-linux-arm64@2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-2.1.2.tgz#22555e28382af2922e7450634c8a2f240bb9eb82" - integrity sha512-vHZ2JiOWF2+DN9lzltGbhtQNzDo8fKFGrf37UJrgqxU0yvtERrzUugnfnX1wmVfFhSsF8OxrfqiNOUc5hko1Zg== +"@msgpackr-extract/msgpackr-extract-linux-arm64@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-2.2.0.tgz#986179c38b10ac41fbdaf7d036c825cbc72855d9" + integrity sha512-hlxxLdRmPyq16QCutUtP8Tm6RDWcyaLsRssaHROatgnkOxdleMTgetf9JsdncL8vLh7FVy/RN9i3XR5dnb9cRA== -"@msgpackr-extract/msgpackr-extract-linux-arm@2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-2.1.2.tgz#ffb6ae1beea7ac572b6be6bf2a8e8162ebdd8be7" - integrity sha512-42R4MAFeIeNn+L98qwxAt360bwzX2Kf0ZQkBBucJ2Ircza3asoY4CDbgiu9VWklq8gWJVSJSJBwDI+c/THiWkA== +"@msgpackr-extract/msgpackr-extract-linux-arm@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-2.2.0.tgz#15f2c6fe9e0adc06c21af7e95f484ff4880d79ce" + integrity sha512-SaJ3Qq4lX9Syd2xEo9u3qPxi/OB+5JO/ngJKK97XDpa1C587H9EWYO6KD8995DAjSinWvdHKRrCOXVUC5fvGOg== -"@msgpackr-extract/msgpackr-extract-linux-x64@2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-2.1.2.tgz#7caf62eebbfb1345de40f75e89666b3d4194755f" - integrity sha512-RjRoRxg7Q3kPAdUSC5EUUPlwfMkIVhmaRTIe+cqHbKrGZ4M6TyCA/b5qMaukQ/1CHWrqYY2FbKOAU8Hg0pQFzg== +"@msgpackr-extract/msgpackr-extract-linux-x64@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-2.2.0.tgz#30cae5c9a202f3e1fa1deb3191b18ffcb2f239a2" + integrity sha512-94y5PJrSOqUNcFKmOl7z319FelCLAE0rz/jPCWS+UtdMZvpa4jrQd+cJPQCLp2Fes1yAW/YUQj/Di6YVT3c3Iw== -"@msgpackr-extract/msgpackr-extract-win32-x64@2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-2.1.2.tgz#f2d8b9ddd8d191205ed26ce54aba3dfc5ae3e7c9" - integrity sha512-rIZVR48zA8hGkHIK7ED6+ZiXsjRCcAVBJbm8o89OKAMTmEAQ2QvoOxoiu3w2isAaWwzgtQIOFIqHwvZDyLKCvw== +"@msgpackr-extract/msgpackr-extract-win32-x64@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-2.2.0.tgz#016d855b6bc459fd908095811f6826e45dd4ba64" + integrity sha512-XrC0JzsqQSvOyM3t04FMLO6z5gCuhPE6k4FXuLK5xf52ZbdvcFe1yBmo7meCew9B8G2f0T9iu9t3kfTYRYROgA== "@shopify/jest-koa-mocks@5.0.1": version "5.0.1" @@ -851,9 +665,9 @@ "@hapi/hoek" "^9.0.0" "@sideway/formula@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.0.tgz#fe158aee32e6bd5de85044be615bc08478a0a13c" - integrity sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg== + version "3.0.1" + resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f" + integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg== "@sideway/pinpoint@^2.0.0": version "2.0.0" @@ -871,9 +685,9 @@ integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== "@sinonjs/commons@^1.7.0": - version "1.8.3" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d" - integrity sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ== + version "1.8.6" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.6.tgz#80c516a4dc264c2a69115e7578d62581ff455ed9" + integrity sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ== dependencies: type-detect "4.0.8" @@ -884,6 +698,80 @@ dependencies: "@sinonjs/commons" "^1.7.0" +"@swc/core-darwin-arm64@1.3.25": + version "1.3.25" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.25.tgz#01ce7b8a88b545a4fc5283ed6f96b22c5733d6c4" + integrity sha512-8PWAVcjTJyj2VrqPBFOIi2w2P0Z8kOCbzHW3+pe+bSXxfGMG0MKPl5U2IXhsEL0ovm4xSFlqW0yygpoP3MmRPw== + +"@swc/core-darwin-x64@1.3.25": + version "1.3.25" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.3.25.tgz#9fad102c507011f42c5a5d1f84919b81ab96d7f8" + integrity sha512-5DHGiMYFEj5aa208tCjo7Sn5tiG4xPz+4gUiWVlglxqXFptkNim5xu/1G6VYm5Zk7dI5jJkjTU76GQG7IRvPug== + +"@swc/core-linux-arm-gnueabihf@1.3.25": + version "1.3.25" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.25.tgz#ecf3a34899fdbdc742523524caab29c0db97a6ad" + integrity sha512-YNfLxv9PhZk+jrJbpR1mMrYBUkufo0hiFv3S1OrX3l8edsIP4wPND5w9ZH0Oi898f6Jg9DBrY2zXJMQ+gWkbvA== + +"@swc/core-linux-arm64-gnu@1.3.25": + version "1.3.25" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.25.tgz#50524c9db2dbf874570e45f0a66e0283f02bc2d9" + integrity sha512-kS+spM5/xQ6QvWF1ms3byfjnhUlpjTfFwgCyHnIKgjvsYkDa+vkAIhKq6HuEdaTPaCRCjts0Zarhub1nClUU0g== + +"@swc/core-linux-arm64-musl@1.3.25": + version "1.3.25" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.25.tgz#f04a3d3784cff14f96ad9901861485ec0fa14ebf" + integrity sha512-vM3D7LWmjotUAJ2D4F+L+dspFeWrcPNVh0o8TCoTOYCt8DPD5YsUKTpIgOsZ+gReeWUAnNTh0Btx5pGGVfajGA== + +"@swc/core-linux-x64-gnu@1.3.25": + version "1.3.25" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.25.tgz#761fb020b8a0130e4dccc9c8dce355fa06df63f4" + integrity sha512-xUCLLMDlYa/zB8BftVa4SrxuVpcDxkltCfmBg5r2pZPVskhC5ZJsQZ/AvWNChoAB11shRhjTaWDlmxJEsa7TIg== + +"@swc/core-linux-x64-musl@1.3.25": + version "1.3.25" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.25.tgz#f944ee48c972ebdcb3e6d6fd62d67eb98dbb1268" + integrity sha512-QzHU3BIaUVRSFNsUn3Qxx1vgtF/f5NqsFMAAPSq9Y8Yq5nrlc2t7cNuOROxHLbUqE+NPUp6+RglleJMoeWz5mA== + +"@swc/core-win32-arm64-msvc@1.3.25": + version "1.3.25" + resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.25.tgz#af63ae850ef6e7322e8a5a0959529e96096239d2" + integrity sha512-77VSVtneVOAUL4zkRyQZ6pWVpTsVVdqwly/DKnRnloglGKxYuk5DG5MUBsL72Nnfv4OCHjZ27eI3NUrpLsUb2Q== + +"@swc/core-win32-ia32-msvc@1.3.25": + version "1.3.25" + resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.25.tgz#96a869aa4b4c41c44c9c9893ac4aad68d1233022" + integrity sha512-kz0v3K3H6OPEZR3ry72Ad/6C5GrZBRRUk69K58LORQ8tZXQD3UGl85pUbQqyHl8fR5NU76Muxgovj9CI9iTHGA== + +"@swc/core-win32-x64-msvc@1.3.25": + version "1.3.25" + resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.25.tgz#9035c11626653322a404f3f44af11a02d989094c" + integrity sha512-nmQOAzIpNRRnupWzkenJmW4i+h1M76cVNUqEU2MjmtesEkRZEGqv//jefXiyCP2zcbeLNLKiB2ptVJhpd1BvRA== + +"@swc/core@^1.3.25": + version "1.3.25" + resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.3.25.tgz#53786ea51fac319684d6822de1738eb55b73a4b7" + integrity sha512-wqzvM/wu6OsTVYPMStOpm7kIQcPX3GoZ0sC85qzDdsCxmJ1rmItLAD91sXPUmmdk0XqPYjLgT9MRDEIP5woz4g== + optionalDependencies: + "@swc/core-darwin-arm64" "1.3.25" + "@swc/core-darwin-x64" "1.3.25" + "@swc/core-linux-arm-gnueabihf" "1.3.25" + "@swc/core-linux-arm64-gnu" "1.3.25" + "@swc/core-linux-arm64-musl" "1.3.25" + "@swc/core-linux-x64-gnu" "1.3.25" + "@swc/core-linux-x64-musl" "1.3.25" + "@swc/core-win32-arm64-msvc" "1.3.25" + "@swc/core-win32-ia32-msvc" "1.3.25" + "@swc/core-win32-x64-msvc" "1.3.25" + +"@swc/jest@^0.2.24": + version "0.2.24" + resolved "https://registry.yarnpkg.com/@swc/jest/-/jest-0.2.24.tgz#35d9377ede049613cd5fdd6c24af2b8dcf622875" + integrity sha512-fwgxQbM1wXzyKzl1+IW0aGrRvAA8k0Y3NxFhKigbPjOJ4mCKnWEcNX9HQS3gshflcxq8YKhadabGUVfdwjCr6Q== + dependencies: + "@jest/create-cache-key-function" "^27.4.2" + jsonc-parser "^3.2.0" + "@szmarczak/http-timer@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" @@ -930,9 +818,9 @@ "@types/node" "*" "@types/babel__core@^7.1.14": - version "7.1.19" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.19.tgz#7b497495b7d1b4812bdb9d02804d0576f43ee460" - integrity sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw== + version "7.1.20" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.20.tgz#e168cdd612c92a2d335029ed62ac94c95b362359" + integrity sha512-PVb6Bg2QuscZ30FvOU7z4guG6c926D9YRvOxEaelzndpMsvP+YM74Q/dAFASpg2l6+XLalxSGxcq/lrgYWZtyQ== dependencies: "@babel/parser" "^7.1.0" "@babel/types" "^7.0.0" @@ -956,16 +844,16 @@ "@babel/types" "^7.0.0" "@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": - version "7.17.1" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.17.1.tgz#1a0e73e8c28c7e832656db372b779bfd2ef37314" - integrity sha512-kVzjari1s2YVi77D3w1yuvohV2idweYXMCDzqBiVNN63TcDWrIlTVOYpqVrvbbyOE/IyzBoTKF0fdnLPEORFxA== + version "7.18.3" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.18.3.tgz#dfc508a85781e5698d5b33443416b6268c4b3e8d" + integrity sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w== dependencies: "@babel/types" "^7.3.0" "@types/bluebird@*": - version "3.5.36" - resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.36.tgz#00d9301d4dc35c2f6465a8aec634bb533674c652" - integrity sha512-HBNx4lhkxN7bx6P0++W8E289foSu8kO8GCk2unhuVggO+cE7rh9DhZUyPhUxNRG9m+5B5BTKxZQ5ZP92x/mx9Q== + version "3.5.38" + resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.38.tgz#7a671e66750ccd21c9fc9d264d0e1e5330bc9908" + integrity sha512-yR/Kxc0dd4FfwtEoLZMoqJbM/VE/W7hXn/MIjb+axcwag0iFmSPK7OBUZq1YWLynJUoWQkfUrI7T0HDqGApNSg== "@types/body-parser@*": version "1.19.2" @@ -1009,29 +897,29 @@ dependencies: "@types/ms" "*" -"@types/express-serve-static-core@^4.17.18": - version "4.17.28" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz#c47def9f34ec81dc6328d0b1b5303d1ec98d86b8" - integrity sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig== +"@types/express-serve-static-core@^4.17.31": + version "4.17.32" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.32.tgz#93dda387f5516af616d8d3f05f2c4c79d81e1b82" + integrity sha512-aI5h/VOkxOF2Z1saPy0Zsxs5avets/iaiAJYznQFm5By/pamU31xWKL//epiF4OfUA2qTOc9PV6tCUjhO8wlZA== dependencies: "@types/node" "*" "@types/qs" "*" "@types/range-parser" "*" "@types/express@*": - version "4.17.13" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034" - integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA== + version "4.17.15" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.15.tgz#9290e983ec8b054b65a5abccb610411953d417ff" + integrity sha512-Yv0k4bXGOH+8a+7bELd2PqHQsuiANB+A8a4gnQrkRWzrkKlb6KHaVvyXhqs04sVW/OWlbPyYxRgYlIXLfrufMQ== dependencies: "@types/body-parser" "*" - "@types/express-serve-static-core" "^4.17.18" + "@types/express-serve-static-core" "^4.17.31" "@types/qs" "*" "@types/serve-static" "*" "@types/graceful-fs@^4.1.3": - version "4.1.5" - resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" - integrity sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw== + version "4.1.6" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.6.tgz#e14b2576a1c25026b7f02ede1de3b84c3a1efeae" + integrity sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw== dependencies: "@types/node" "*" @@ -1041,9 +929,9 @@ integrity sha512-FyAOrDuQmBi8/or3ns4rwPno7/9tJTijVW6aQQjK02+kOQ8zmoNg2XJtAuQhvQcy1ASJq38wirX5//9J1EqoUA== "@types/http-errors@*": - version "1.8.2" - resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-1.8.2.tgz#7315b4c4c54f82d13fa61c228ec5c2ea5cc9e0e1" - integrity sha512-EqX+YQxINb+MeXaIqYDASb6U6FCHbWjkj4a1CKDBks3d/QiB2+PqBLyO72vLDgAO1wUI4O+9gweRcQK11bTL/w== + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.1.tgz#20172f9578b225f6c7da63446f56d4ce108d5a65" + integrity sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ== "@types/ioredis@4.28.0": version "4.28.0" @@ -1091,7 +979,30 @@ dependencies: "@types/koa" "*" -"@types/koa@*", "@types/koa@2.13.4": +"@types/koa-pino-logger@3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/koa-pino-logger/-/koa-pino-logger-3.0.0.tgz#275d4b000abc14b1928dc2e9ab476c8296a64b6a" + integrity sha512-sP+12JNX01q+nHpCRqkVIuLjaRemQEfDoFg0evpTnjUEI3jUI2ZrOkhQ5coxn3yVm2tedui/2YhlaPn/XrYNWA== + dependencies: + "@types/koa" "*" + "@types/pino" "*" + "@types/pino-http" "*" + +"@types/koa@*": + version "2.13.5" + resolved "https://registry.yarnpkg.com/@types/koa/-/koa-2.13.5.tgz#64b3ca4d54e08c0062e89ec666c9f45443b21a61" + integrity sha512-HSUOdzKz3by4fnqagwthW/1w/yJspTgppyyalPVbgZf8jQWvdIXcVW5h2DGtw4zYntOaeRGx49r1hxoPWrD4aA== + dependencies: + "@types/accepts" "*" + "@types/content-disposition" "*" + "@types/cookies" "*" + "@types/http-assert" "*" + "@types/http-errors" "*" + "@types/keygrip" "*" + "@types/koa-compose" "*" + "@types/node" "*" + +"@types/koa@2.13.4": version "2.13.4" resolved "https://registry.yarnpkg.com/@types/koa/-/koa-2.13.4.tgz#10620b3f24a8027ef5cbae88b393d1b31205726b" integrity sha512-dfHYMfU+z/vKtQB7NUrthdAEiSvnLebvBjwHtfFmpZmB7em2N3WVQdHgnFq+xvyVgxW5jKDmjWfLD3lw4g4uTw== @@ -1110,10 +1021,10 @@ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.180.tgz#4ab7c9ddfc92ec4a887886483bc14c79fb380670" integrity sha512-XOKXa1KIxtNXgASAnwj7cnttJxS4fksBRywK/9LzRV5YxrF80BXZIGeQSuoESQ/VkUj30Ae0+YcuHc15wJCB2g== -"@types/mime@^1": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" - integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== +"@types/mime@*": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10" + integrity sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA== "@types/ms@*": version "0.7.31" @@ -1129,15 +1040,53 @@ form-data "^3.0.0" "@types/node@*": - version "17.0.41" - resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.41.tgz#1607b2fd3da014ae5d4d1b31bc792a39348dfb9b" - integrity sha512-xA6drNNeqb5YyV5fO3OAEsnXLfO7uF0whiOfPTz5AeDo8KeZFmODKnvwPymMNO8qE/an8pVY/O50tig2SQCrGw== + version "18.11.18" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.18.tgz#8dfb97f0da23c2293e554c5a50d61ef134d7697f" + integrity sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA== "@types/node@14.18.20": version "14.18.20" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.20.tgz#268f028b36eaf51181c3300252f605488c4f0650" integrity sha512-Q8KKwm9YqEmUBRsqJ2GWJDtXltBDxTdC4m5vTdXBolu2PeQh8LX+f6BTwU+OuXPu37fLxoN6gidqBmnky36FXA== +"@types/pino-http@*", "@types/pino-http@5.8.1": + version "5.8.1" + resolved "https://registry.yarnpkg.com/@types/pino-http/-/pino-http-5.8.1.tgz#ebb194750ad2f9245c3028b5d2c4e6d64f685ba9" + integrity sha512-A9MW6VCnx5ii7s+Fs5aFIw+aSZcBCpsZ/atpxamu8tTsvWFacxSf2Hrn1Ohn1jkVRB/LiPGOapRXcFawDBnDnA== + dependencies: + "@types/pino" "6.3" + +"@types/pino-pretty@*": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@types/pino-pretty/-/pino-pretty-5.0.0.tgz#aa7a61cfd553b051764acfa0a49872f7a09a1722" + integrity sha512-N1uzqSzioqz8R3AkDbSJwcfDWeI3YMPNapSQQhnB2ISU4NYgUIcAh+hYT5ygqBM+klX4htpEhXMmoJv3J7GrdA== + dependencies: + pino-pretty "*" + +"@types/pino-std-serializers@*": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/pino-std-serializers/-/pino-std-serializers-4.0.0.tgz#1e28b80b554c8222858e99a4e0fc77fd070e10e8" + integrity sha512-gXfUZx2xIBbFYozGms53fT0nvkacx/+62c8iTxrEqH5PkIGAQvDbXg2774VWOycMPbqn5YJBQ3BMsg4Li3dWbg== + dependencies: + pino-std-serializers "*" + +"@types/pino@*": + version "7.0.5" + resolved "https://registry.yarnpkg.com/@types/pino/-/pino-7.0.5.tgz#1c84a81b924a6a9e263dbb581dffdbad7a3c60c4" + integrity sha512-wKoab31pknvILkxAF8ss+v9iNyhw5Iu/0jLtRkUD74cNfOOLJNnqfFKAv0r7wVaTQxRZtWrMpGfShwwBjOcgcg== + dependencies: + pino "*" + +"@types/pino@6.3": + version "6.3.12" + resolved "https://registry.yarnpkg.com/@types/pino/-/pino-6.3.12.tgz#4425db6ced806109c3df957100cba9dfcd73c228" + integrity sha512-dsLRTq8/4UtVSpJgl9aeqHvbh6pzdmjYD3C092SYgLD2TyoCqHpTJk6vp8DvCTGGc7iowZ2MoiYiVUUCcu7muw== + dependencies: + "@types/node" "*" + "@types/pino-pretty" "*" + "@types/pino-std-serializers" "*" + sonic-boom "^2.1.0" + "@types/pouchdb-adapter-cordova-sqlite@*": version "1.0.1" resolved "https://registry.yarnpkg.com/@types/pouchdb-adapter-cordova-sqlite/-/pouchdb-adapter-cordova-sqlite-1.0.1.tgz#49e5ee6df7cc0c23196fcb340f43a560e74eb1d6" @@ -1223,9 +1172,9 @@ "@types/pouchdb-find" "*" "@types/pouchdb-find@*": - version "6.3.7" - resolved "https://registry.yarnpkg.com/@types/pouchdb-find/-/pouchdb-find-6.3.7.tgz#f713534a53c1a7f3fd8fbbfb74131a1b04711ddc" - integrity sha512-b2dr9xoZRK5Mwl8UiRA9l5j9mmCxNfqXuu63H1KZHwJLILjoIIz7BntCvM0hnlnl7Q8P8wORq0IskuaMq5Nnnw== + version "7.3.0" + resolved "https://registry.yarnpkg.com/@types/pouchdb-find/-/pouchdb-find-7.3.0.tgz#b917030e9f4bf6e56bf8c3b9fe4b2a25e989009a" + integrity sha512-sFPli5tBjGX9UfXioik1jUzPdcN84eV82n0lmEFuoPepWqkLjQcyri0eOa++HYOaNPyMDhKFBqEALEZivK2dRg== dependencies: "@types/pouchdb-core" "*" @@ -1285,9 +1234,9 @@ "@types/pouchdb-replication" "*" "@types/prettier@^2.1.5": - version "2.6.3" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.6.3.tgz#68ada76827b0010d0db071f739314fa429943d0a" - integrity sha512-ymZk3LEC/fsut+/Q5qejp6R9O1rMxz3XaRHDV6kX8MrGAhOSPqVARbDi+EZvInBpw+BnCX3TD240byVkOfQsHg== + version "2.7.2" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.2.tgz#6c2324641cc4ba050a8c710b2b251b377581fbf0" + integrity sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg== "@types/qs@*": version "6.9.7" @@ -1320,11 +1269,11 @@ integrity sha512-4g1jrL98mdOIwSOUh6LTlB0Cs9I0dQPwINUhBg7C6pN4HLr8GS8xsksJxilW6S6dQHVi2K/o+lQuQcg7LroCnw== "@types/serve-static@*": - version "1.13.10" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.10.tgz#f5e0ce8797d2d7cc5ebeda48a52c96c4fa47a8d9" - integrity sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ== + version "1.15.0" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.0.tgz#c7930ff61afb334e121a9da780aac0d9b8f34155" + integrity sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg== dependencies: - "@types/mime" "^1" + "@types/mime" "*" "@types/node" "*" "@types/stack-utils@^2.0.0": @@ -1362,10 +1311,17 @@ resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== +"@types/yargs@^16.0.0": + version "16.0.5" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-16.0.5.tgz#12cc86393985735a283e387936398c2f9e5f88e3" + integrity sha512-AxO/ADJOBFJScHbWhq2xAhlWP24rY4aCEG/NFaMvbT3X2MgRsLjhjQwsn0Zi5zn0LG9jUhCCZMeX9Dkuw6k+vQ== + dependencies: + "@types/yargs-parser" "*" + "@types/yargs@^17.0.8": - version "17.0.13" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.13.tgz#34cced675ca1b1d51fcf4d34c3c6f0fa142a5c76" - integrity sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg== + version "17.0.19" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.19.tgz#8dbecdc9ab48bee0cb74f6e3327de3fa0d0c98ae" + integrity sha512-cAx3qamwaYX9R0fzOIZAlFpo4A+1uBVCxqpKz9D26uTF4srRXaGTTsikQmaotCtNdbhzyUH7ft6p9ktz9s6UNQ== dependencies: "@types/yargs-parser" "*" @@ -1374,7 +1330,7 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== -abort-controller@3.0.0: +abort-controller@3.0.0, abort-controller@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== @@ -1484,9 +1440,9 @@ ansi-styles@^5.0.0: integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== anymatch@^3.0.3, anymatch@~3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" - integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== dependencies: normalize-path "^3.0.0" picomatch "^2.0.4" @@ -1538,6 +1494,18 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== +atomic-sleep@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" + integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== + +aws-cloudfront-sign@2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/aws-cloudfront-sign/-/aws-cloudfront-sign-2.2.0.tgz#3910f5a6d0d90fec07f2b4ef8ab07f3eefb5625d" + integrity sha512-qG+rwZMP3KRTPPbVmWY8DlrT56AkA4iVOeo23vkdK2EXeW/brJFN2haSNKzVz+oYhFMEIzVVloeAcrEzuRkuVQ== + dependencies: + lodash "^3.6.0" + aws-sdk@2.1030.0: version "2.1030.0" resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1030.0.tgz#24a856af3d2b8b37c14a8f59974993661c66fd82" @@ -1559,14 +1527,14 @@ aws-sign2@~0.7.0: integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== aws4@^1.8.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" - integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== + version "1.12.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3" + integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg== axios-retry@^3.1.9: - version "3.2.5" - resolved "https://registry.yarnpkg.com/axios-retry/-/axios-retry-3.2.5.tgz#64952992837c7d9a12eec156a2694a7945f60895" - integrity sha512-a8umkKbfIkTiYJQLx3v3TzKM85TGKB8ZQYz4zwykt2fpO64TsRlUhjaPaAb3fqMWCXFm2YhWcd8V5FHDKO9bSA== + version "3.3.1" + resolved "https://registry.yarnpkg.com/axios-retry/-/axios-retry-3.3.1.tgz#47624646138aedefbad2ac32f226f4ee94b6dcab" + integrity sha512-RohAUQTDxBSWLFEnoIG/6bvmy8l3TfpkclgStjl5MDCMBDgapAWCmr1r/9harQfWC8bzLC8job6UcL1A1Yc+/Q== dependencies: "@babel/runtime" "^7.15.4" is-retry-allowed "^2.2.0" @@ -1579,9 +1547,9 @@ axios@0.24.0: follow-redirects "^1.14.4" axios@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.1.3.tgz#8274250dada2edf53814ed7db644b9c2866c1e35" - integrity sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA== + version "1.2.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.2.2.tgz#72681724c6e6a43a9fea860fc558127dbe32f9f1" + integrity sha512-bz/J4gS2S3I7mpN/YZfGFTqhXTYzRho8Ay38w2otuuDR322KzFIWm/4W2K6gIwvWaws5n+mnb7D1lN9uD+QH6Q== dependencies: follow-redirects "^1.15.0" form-data "^4.0.0" @@ -1723,6 +1691,13 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" @@ -1730,17 +1705,6 @@ braces@^3.0.2, braces@~3.0.2: dependencies: fill-range "^7.0.1" -browserslist@^4.20.2: - version "4.20.4" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.20.4.tgz#98096c9042af689ee1e0271333dbc564b8ce4477" - integrity sha512-ok1d+1WpnU24XYN7oC3QWgTyMhY/avPJ/r9T00xxvUOIparA/gc+UPUMaod3i+G6s+nI2nUb9xZ5k794uIwShw== - dependencies: - caniuse-lite "^1.0.30001349" - electron-to-chromium "^1.4.147" - escalade "^3.1.1" - node-releases "^2.0.5" - picocolors "^1.0.0" - browserslist@^4.21.3: version "4.21.4" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987" @@ -1797,6 +1761,14 @@ buffer@^5.5.0, buffer@^5.6.0: base64-js "^1.3.1" ieee754 "^1.1.13" +buffer@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + bull@4.10.1: version "4.10.1" resolved "https://registry.yarnpkg.com/bull/-/bull-4.10.1.tgz#f14974b6089358b62b495a2cbf838aadc098e43f" @@ -1856,15 +1828,10 @@ camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30001349: - version "1.0.30001352" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001352.tgz#cc6f5da3f983979ad1e2cdbae0505dccaa7c6a12" - integrity sha512-GUgH8w6YergqPQDGWhJGt8GDRnY0L/iJVQcU3eJ46GYf52R8tk0Wxp0PymuFVZboJYXGiCqwozAYZNRjVj6IcA== - caniuse-lite@^1.0.30001400: - version "1.0.30001431" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001431.tgz#e7c59bd1bc518fae03a4656be442ce6c4887a795" - integrity sha512-zBUoFU0ZcxpvSt9IU66dXVT/3ctO1cy4y9cscs1szkPlcWb6pasYM144GqrUygUbT+k7cmUCW61cvskjcv0enQ== + version "1.0.30001442" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001442.tgz#40337f1cf3be7c637b061e2f78582dc1daec0614" + integrity sha512-239m03Pqy0hwxYPYR5JwOIxRJfLTWtle9FV8zosfV5pHg+/51uD4nxcUlM8+mWWGfwKtt8lJNHnD3cWw9VZ6ow== caseless@~0.12.0: version "0.12.0" @@ -1888,10 +1855,10 @@ chalk@^4.0.0, chalk@^4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chance@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chance/-/chance-1.1.3.tgz#414f08634ee479c7a316b569050ea20751b82dd3" - integrity sha512-XeJsdoVAzDb1WRPRuMBesRSiWpW1uNTo5Fd7mYxPJsAfgX71+jfuCOHOdbyBz2uAUZ8TwKcXgWk3DMedFfJkbg== +chance@1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/chance/-/chance-1.1.8.tgz#5d6c2b78c9170bf6eb9df7acdda04363085be909" + integrity sha512-v7fi5Hj2VbR6dJEGRWLmJBA83LJMS47pkAbmROFxHWd9qmE1esHRZW8Clf1Fhzr3rjxnNZVCjOEv/ivFxeIMtg== char-regex@^1.0.2: version "1.0.2" @@ -1934,9 +1901,9 @@ ci-info@^2.0.0: integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== ci-info@^3.2.0: - version "3.3.1" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.1.tgz#58331f6f472a25fe3a50a351ae3052936c2c7f32" - integrity sha512-SXgeMX9VwDe7iFFaEWkA5AstuER9YKqy4EhHqr4DVqkwmD9rpVimkMKWHdjn30Ja45txyjhSn63lVX69eVCckg== + version "3.7.1" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.7.1.tgz#708a6cdae38915d597afdf3b145f2f8e1ff55f3f" + integrity sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w== cjs-module-lexer@^1.0.0: version "1.2.2" @@ -1963,16 +1930,16 @@ clone-buffer@1.0.0: integrity sha512-KLLTJWrvwIP+OPfMn0x2PheDEP20RPUcGXj/ERegTgdmPEZylALQldygiqrPPu8P45uNuPs7ckmReLY6v/iA5g== clone-response@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" - integrity sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q== + version "1.0.3" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.3.tgz#af2032aa47816399cf5f0a1d0db902f517abb8c3" + integrity sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA== dependencies: mimic-response "^1.0.0" cluster-key-slot@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz#30474b2a981fb12172695833052bc0d01336d10d" - integrity sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw== + version "1.1.2" + resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz#88ddaa46906e303b5de30d3153b7d9fe0a0c19ac" + integrity sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA== co@^4.6.0: version "4.6.0" @@ -2013,6 +1980,11 @@ color-support@^1.1.2: resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== +colorette@^2.0.7: + version "2.0.19" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" + integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== + combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" @@ -2060,11 +2032,9 @@ content-type@^1.0.4: integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" - integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== - dependencies: - safe-buffer "~5.1.1" + version "1.9.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" + integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== cookies@~0.8.0: version "0.8.0" @@ -2084,17 +2054,24 @@ core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== +correlation-id@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/correlation-id/-/correlation-id-4.0.0.tgz#c1d3038e5f30d7bfeae5728ff96f27a7506bc2c0" + integrity sha512-WvXtJBlovvOBKqTz/YwWP2gm6CXJZJArfGimp9s/ehmhJMPFbmnPMQe3K60Q9idGNixMvKojMjleyDhZEFdHfg== + dependencies: + uuid "^8.3.1" + create-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== cron-parser@^4.2.1: - version "4.6.0" - resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-4.6.0.tgz#404c3fdbff10ae80eef6b709555d577ef2fd2e0d" - integrity sha512-guZNLMGUgg6z4+eGhmHGw7ft+v6OQeuHzd1gcLxCo9Yg/qoxmG3nindp2/uwGCLizEisf2H0ptqeVXeoCpP6FA== + version "4.7.1" + resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-4.7.1.tgz#1e325a6a18e797a634ada1e2599ece0b6b5ed177" + integrity sha512-WguFaoQ0hQ61SgsCZLHUcNbAvlK0lypKXu62ARguefYmjzaOXIVRNrAmyXzabTwUn4sQvQLkk6bjH+ipGfw8bA== dependencies: - luxon "^3.0.1" + luxon "^3.2.1" cross-spawn@^7.0.3: version "7.0.3" @@ -2122,6 +2099,11 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +dateformat@^4.6.3: + version "4.6.3" + resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-4.6.3.tgz#556fa6497e5217fedb78821424f8a1c22fa3f4b5" + integrity sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA== + debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" @@ -2254,9 +2236,9 @@ double-ended-queue@2.1.0-0: integrity sha512-+BNfZ+deCo8hMNpDqDnvT+c0XpJ5cUa6mqYq89bho2Ifze4URTqRkcwR399hWoTrTkbZ/XJYDgP6rc7pRgffEQ== duplexer3@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" - integrity sha512-CEj8FwwNA4cVH2uFCoHUrmojhYh1vmCdOaneKJXwkeY1i9jnlslVo9dx+hQ5Hl9GnH/Bwy/IjxAyOePyPKYnzA== + version "0.1.5" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.5.tgz#0b5e4d7bad5de8901ea4440624c8e1d20099217e" + integrity sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA== ecc-jsbn@~0.1.1: version "0.1.2" @@ -2278,11 +2260,6 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== -electron-to-chromium@^1.4.147: - version "1.4.150" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.150.tgz#89f0e12505462d5df7e56c5b91aff7e1dfdd33ec" - integrity sha512-MP3oBer0X7ZeS9GJ0H6lmkn561UxiwOIY9TTkdxVY7lI9G6GVCKfgJaHaDcakwdKxBXA4T3ybeswH/WBIN/KTA== - electron-to-chromium@^1.4.251: version "1.4.284" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592" @@ -2388,6 +2365,11 @@ events@1.1.1: resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" integrity sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw== +events@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + execa@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" @@ -2434,6 +2416,11 @@ extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== +fast-copy@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-3.0.0.tgz#875ebf33b13948ae012b6e51d33da5e6e7571ab8" + integrity sha512-4HzS+9pQ5Yxtv13Lhs1Z1unMXamBdn5nA4bEi1abYpDNSpSp7ODYQ1KPMF6nTatfEzgH6/zPvXKU1zvHiUjWlA== + fast-deep-equal@^3.1.1: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -2444,10 +2431,20 @@ fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== +fast-redact@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.1.2.tgz#d58e69e9084ce9fa4c1a6fa98a3e1ecf5d7839aa" + integrity sha512-+0em+Iya9fKGfEQGcd62Yv6onjBmmhV1uh86XVfOU8VwAe6kaFdQCWI9s0/Nnugx5Vd9tdbZ7e6gE2tR9dzXdw== + +fast-safe-stringify@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" + integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== + fb-watchman@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" - integrity sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg== + version "2.0.2" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" + integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== dependencies: bser "2.1.1" @@ -2494,12 +2491,7 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" -follow-redirects@^1.14.4: - version "1.15.1" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5" - integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA== - -follow-redirects@^1.15.0: +follow-redirects@^1.14.4, follow-redirects@^1.15.0: version "1.15.2" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== @@ -2662,10 +2654,21 @@ glob@^7.1.3, glob@^7.1.4: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^8.0.0: + version "8.0.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-8.0.3.tgz#415c6eb2deed9e502c68fa44a272e6da6eeca42e" + integrity sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^5.0.1" + once "^1.3.0" + global-dirs@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.0.tgz#70a76fe84ea315ab37b1f5576cbde7d48ef72686" - integrity sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA== + version "3.0.1" + resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.1.tgz#0c488971f066baceda21447aecb1a8b911d22485" + integrity sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA== dependencies: ini "2.0.0" @@ -2748,6 +2751,14 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" +help-me@^4.0.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/help-me/-/help-me-4.2.0.tgz#50712bfd799ff1854ae1d312c36eafcea85b0563" + integrity sha512-TAOnTB8Tz5Dw8penUuzHVrKNKlCIbwwbHnXraNJxPwf8LRtE2HlM84RYuezMFcwOJmoYOCWVDyJ8TQGxn9PgxA== + dependencies: + glob "^8.0.0" + readable-stream "^3.6.0" + html-escaper@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" @@ -2762,9 +2773,9 @@ http-assert@^1.3.0: http-errors "~1.8.0" http-cache-semantics@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" - integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== + version "4.1.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" + integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== http-cookie-agent@^4.0.2: version "4.0.2" @@ -2811,7 +2822,7 @@ ieee754@1.1.13: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== -ieee754@^1.1.13, ieee754@^1.1.4: +ieee754@^1.1.13, ieee754@^1.1.4, ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -2940,10 +2951,10 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" -is-core-module@^2.8.1: - version "2.9.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69" - integrity sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A== +is-core-module@^2.9.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" + integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== dependencies: has "^1.0.3" @@ -3050,9 +3061,9 @@ istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz#31d18bdd127f825dd02ea7bfdfd906f8ab840e9f" - integrity sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A== + version "5.2.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" + integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== dependencies: "@babel/core" "^7.12.3" "@babel/parser" "^7.14.7" @@ -3079,9 +3090,9 @@ istanbul-lib-source-maps@^4.0.0: source-map "^0.6.1" istanbul-reports@^3.1.3: - version "3.1.4" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.4.tgz#1b6f068ecbc6c331040aab5741991273e609e40c" - integrity sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw== + version "3.1.5" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.5.tgz#cc9a6ab25cb25659810e4785ed9d9fb742578bae" + integrity sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w== dependencies: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" @@ -3296,9 +3307,9 @@ jest-mock@^28.1.3: "@types/node" "*" jest-pnp-resolver@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" - integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w== + version "1.2.3" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" + integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== jest-regex-util@^28.0.2: version "28.0.2" @@ -3490,6 +3501,11 @@ join-component@^1.1.0: resolved "https://registry.yarnpkg.com/join-component/-/join-component-1.1.0.tgz#b8417b750661a392bee2c2537c68b2a9d4977cd5" integrity sha512-bF7vcQxbODoGK1imE2P9GS9aw4zD0Sd+Hni68IMZLj7zRnquH7dXUmMw9hDI5S/Jzt7q+IyTXN0rSg2GI0IKhQ== +joycon@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03" + integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw== + js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -3538,12 +3554,27 @@ json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== -json5@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" - integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== +json5@^2.2.1, json5@^2.2.2: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== -jsonwebtoken@8.5.1, jsonwebtoken@^8.2.0: +jsonc-parser@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76" + integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w== + +jsonwebtoken@9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz#d0faf9ba1cc3a56255fe49c0961a67e520c1926d" + integrity sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw== + dependencies: + jws "^3.2.2" + lodash "^4.17.21" + ms "^2.1.1" + semver "^7.3.8" + +jsonwebtoken@^8.2.0: version "8.5.1" resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d" integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w== @@ -3625,7 +3656,7 @@ koa-passport@4.1.4: dependencies: passport "^0.4.0" -koa@2.13.4, koa@^2.13.4: +koa@2.13.4: version "2.13.4" resolved "https://registry.yarnpkg.com/koa/-/koa-2.13.4.tgz#ee5b0cb39e0b8069c38d115139c774833d32462e" integrity sha512-43zkIKubNbnrULWlHdN5h1g3SEKXOEzoAlRsHOTFpnlDu8JlAOZSMJBLULusuXRequboiwJcj5vtYXKB3k7+2g== @@ -3654,6 +3685,35 @@ koa@2.13.4, koa@^2.13.4: type-is "^1.6.16" vary "^1.1.2" +koa@^2.13.4: + version "2.14.1" + resolved "https://registry.yarnpkg.com/koa/-/koa-2.14.1.tgz#defb9589297d8eb1859936e777f3feecfc26925c" + integrity sha512-USJFyZgi2l0wDgqkfD27gL4YGno7TfUkcmOe6UOLFOVuN+J7FwnNu4Dydl4CUQzraM1lBAiGed0M9OVJoT0Kqw== + dependencies: + accepts "^1.3.5" + cache-content-type "^1.0.0" + content-disposition "~0.5.2" + content-type "^1.0.4" + cookies "~0.8.0" + debug "^4.3.2" + delegates "^1.0.0" + depd "^2.0.0" + destroy "^1.0.4" + encodeurl "^1.0.2" + escape-html "^1.0.3" + fresh "~0.5.2" + http-assert "^1.3.0" + http-errors "^1.6.3" + is-generator-function "^1.0.7" + koa-compose "^4.1.0" + koa-convert "^2.0.0" + on-finished "^2.3.0" + only "~0.0.2" + parseurl "^1.3.2" + statuses "^1.5.0" + type-is "^1.6.16" + vary "^1.1.2" + latest-version@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" @@ -3839,6 +3899,11 @@ lodash@4.17.21, lodash@^4.17.21: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== +lodash@^3.6.0: + version "3.10.1" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" + integrity sha512-9mDDwqVIma6OZX79ZlDACZl8sBm0TEnkf99zV3iMA4GzkIT/9hiqP5mY0HoT1iNLCrKc/R1HByV+yJfRWVJryQ== + lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" @@ -3849,6 +3914,13 @@ lowercase-keys@^2.0.0: resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -3861,10 +3933,10 @@ ltgt@2.2.1, ltgt@^2.1.2, ltgt@~2.2.0: resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" integrity sha512-AI2r85+4MquTw9ZYqabu4nMwy9Oftlfa/e/52t9IjtfG+mGBbTNdAoZ3RQKLHR6r0wQnwZnPIEh/Ya6XTWAKNA== -luxon@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.0.4.tgz#d179e4e9f05e092241e7044f64aaa54796b03929" - integrity sha512-aV48rGUwP/Vydn8HT+5cdr26YYQiUZ42NM6ToMoaGKwYfWbfLeRkEu1wXWMHBZT6+KyLfcbbtVcoQFCbbPjKlw== +luxon@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.2.1.tgz#14f1af209188ad61212578ea7e3d518d18cee45f" + integrity sha512-QrwPArQCNLAKGO/C+ZIilgIuDnEnKx5QYODdDtbFaxzsbZcc/a7WFq7MhsVYgRlwawLtvOUESTlfJ+hc/USqPg== make-dir@^3.0.0, make-dir@^3.1.0: version "3.1.0" @@ -3968,20 +4040,29 @@ minimatch@^3.0.4, minimatch@^3.1.1: dependencies: brace-expansion "^1.1.7" -minimist@^1.2.0: - version "1.2.6" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" - integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== +minimatch@^5.0.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.2.tgz#0939d7d6f0898acbd1508abe534d1929368a8fff" + integrity sha512-bNH9mmM9qsJ2X4r2Nat1B//1dJVcn3+iBLa3IgqJ7EbGaDNepL9QSHOxN4ng33s52VMMhhIfgCYDk3C4ZmlDAg== + dependencies: + brace-expansion "^2.0.1" -minimist@^1.2.6: +minimist@^1.2.0, minimist@^1.2.6: version "1.2.7" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== minipass@^3.0.0: - version "3.1.6" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.6.tgz#3b8150aa688a711a1521af5e8779c1d3bb4f45ee" - integrity sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ== + version "3.3.6" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" + integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== + dependencies: + yallist "^4.0.0" + +minipass@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-4.0.0.tgz#7cebb0f9fa7d56f0c5b17853cbe28838a8dbbd3b" + integrity sha512-g2Uuh2jEKoht+zvO6vJqXmYpflPqzRBT+Th2h01DKh5z7wbY/AZ2gCQ78cP70YoHPyFdY30YBV5WxgLOEwOykw== dependencies: yallist "^4.0.0" @@ -4013,26 +4094,26 @@ ms@^2.1.1, ms@^2.1.3: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -msgpackr-extract@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/msgpackr-extract/-/msgpackr-extract-2.1.2.tgz#56272030f3e163e1b51964ef8b1cd5e7240c03ed" - integrity sha512-cmrmERQFb19NX2JABOGtrKdHMyI6RUyceaPBQ2iRz9GnDkjBWFjNJC0jyyoOfZl2U/LZE3tQCCQc4dlRyA8mcA== +msgpackr-extract@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/msgpackr-extract/-/msgpackr-extract-2.2.0.tgz#4bb749b58d9764cfdc0d91c7977a007b08e8f262" + integrity sha512-0YcvWSv7ZOGl9Od6Y5iJ3XnPww8O7WLcpYMDwX+PAA/uXLDtyw94PJv9GLQV/nnp3cWlDhMoyKZIQLrx33sWog== dependencies: node-gyp-build-optional-packages "5.0.3" optionalDependencies: - "@msgpackr-extract/msgpackr-extract-darwin-arm64" "2.1.2" - "@msgpackr-extract/msgpackr-extract-darwin-x64" "2.1.2" - "@msgpackr-extract/msgpackr-extract-linux-arm" "2.1.2" - "@msgpackr-extract/msgpackr-extract-linux-arm64" "2.1.2" - "@msgpackr-extract/msgpackr-extract-linux-x64" "2.1.2" - "@msgpackr-extract/msgpackr-extract-win32-x64" "2.1.2" + "@msgpackr-extract/msgpackr-extract-darwin-arm64" "2.2.0" + "@msgpackr-extract/msgpackr-extract-darwin-x64" "2.2.0" + "@msgpackr-extract/msgpackr-extract-linux-arm" "2.2.0" + "@msgpackr-extract/msgpackr-extract-linux-arm64" "2.2.0" + "@msgpackr-extract/msgpackr-extract-linux-x64" "2.2.0" + "@msgpackr-extract/msgpackr-extract-win32-x64" "2.2.0" msgpackr@^1.5.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.7.2.tgz#68d6debf5999d6b61abb6e7046a689991ebf7261" - integrity sha512-mWScyHTtG6TjivXX9vfIy2nBtRupaiAj0HQ2mtmpmYujAmqZmaaEVPaSZ1NKLMvicaMLFzEaMk0ManxMRg8rMQ== + version "1.8.1" + resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.8.1.tgz#2298aed8a14f83e99df77d344cbda3e436f29b5b" + integrity sha512-05fT4J8ZqjYlR4QcRDIhLCYKUOHXk7C/xa62GzMKj74l3up9k2QZ3LgFc6qWdsPHl91QA2WLWqWc8b8t7GLNNw== optionalDependencies: - msgpackr-extract "^2.1.2" + msgpackr-extract "^2.2.0" napi-macros@~2.0.0: version "2.0.0" @@ -4097,9 +4178,9 @@ node-int64@^0.4.0: integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== node-mocks-http@^1.11.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/node-mocks-http/-/node-mocks-http-1.11.0.tgz#defc0febf6b935f08245397d47534a8de592996e" - integrity sha512-jS/WzSOcKbOeGrcgKbenZeNhxUNnP36Yw11+hL4TTxQXErGfqYZ+MaYNNvhaTiGIJlzNSqgQkk9j8dSu1YWSuw== + version "1.12.1" + resolved "https://registry.yarnpkg.com/node-mocks-http/-/node-mocks-http-1.12.1.tgz#838e176019daf177caff6bb8534e3a32646e7531" + integrity sha512-jrA7Sn3qI6GsHgWtUW3gMj0vO6Yz0nJjzg3jRZYjcfj4tzi8oWPauDK1qHVJoAxTbwuDHF1JiM9GISZ/ocI/ig== dependencies: accepts "^1.3.7" content-disposition "^0.5.3" @@ -4112,15 +4193,10 @@ node-mocks-http@^1.11.0: range-parser "^1.2.0" type-is "^1.6.18" -node-releases@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.5.tgz#280ed5bc3eba0d96ce44897d8aee478bfb3d9666" - integrity sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q== - node-releases@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" - integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== + version "2.0.8" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.8.tgz#0f349cdc8fcfa39a92ac0be9bc48b7706292b9ae" + integrity sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A== nodemon@2.0.16: version "2.0.16" @@ -4199,6 +4275,11 @@ object-inspect@^1.9.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== +on-exit-leak-free@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz#5c703c968f7e7f851885f6459bf8a8a57edc9cc4" + integrity sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w== + on-finished@^2.3.0: version "2.4.1" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" @@ -4418,6 +4499,56 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +pino-abstract-transport@^1.0.0, pino-abstract-transport@v1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-1.0.0.tgz#cc0d6955fffcadb91b7b49ef220a6cc111d48bb3" + integrity sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA== + dependencies: + readable-stream "^4.0.0" + split2 "^4.0.0" + +pino-pretty@*: + version "9.1.1" + resolved "https://registry.yarnpkg.com/pino-pretty/-/pino-pretty-9.1.1.tgz#e7d64c1db98266ca428ab56567b844ba780cd0e1" + integrity sha512-iJrnjgR4FWQIXZkUF48oNgoRI9BpyMhaEmihonHeCnZ6F50ZHAS4YGfGBT/ZVNsPmd+hzkIPGzjKdY08+/yAXw== + dependencies: + colorette "^2.0.7" + dateformat "^4.6.3" + fast-copy "^3.0.0" + fast-safe-stringify "^2.1.1" + help-me "^4.0.1" + joycon "^3.1.1" + minimist "^1.2.6" + on-exit-leak-free "^2.1.0" + pino-abstract-transport "^1.0.0" + pump "^3.0.0" + readable-stream "^4.0.0" + secure-json-parse "^2.4.0" + sonic-boom "^3.0.0" + strip-json-comments "^3.1.1" + +pino-std-serializers@*, pino-std-serializers@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-6.1.0.tgz#307490fd426eefc95e06067e85d8558603e8e844" + integrity sha512-KO0m2f1HkrPe9S0ldjx7za9BJjeHqBku5Ch8JyxETxT8dEFGz1PwgrHaOQupVYitpzbFSYm7nnljxD8dik2c+g== + +pino@*: + version "8.8.0" + resolved "https://registry.yarnpkg.com/pino/-/pino-8.8.0.tgz#1f0d6695a224aa06afc7ad60f2ccc4772d3b9233" + integrity sha512-cF8iGYeu2ODg2gIwgAHcPrtR63ILJz3f7gkogaHC/TXVVXxZgInmNYiIpDYEwgEkxZti2Se6P2W2DxlBIZe6eQ== + dependencies: + atomic-sleep "^1.0.0" + fast-redact "^3.1.1" + on-exit-leak-free "^2.1.0" + pino-abstract-transport v1.0.0 + pino-std-serializers "^6.0.0" + process-warning "^2.0.0" + quick-format-unescaped "^4.0.3" + real-require "^0.2.0" + safe-stable-stringify "^2.3.1" + sonic-boom "^3.1.0" + thread-stream "^2.0.0" + pirates@^4.0.4: version "4.0.5" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b" @@ -4680,6 +4811,16 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== +process-warning@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-2.1.0.tgz#1e60e3bfe8183033bbc1e702c2da74f099422d1a" + integrity sha512-9C20RLxrZU/rFnxWncDkuF6O999NdIf3E1ws4B0ZeY3sRVPzWBMsYDE2lxjxhiXxg464cQTgKUGm8/i6y2YGXg== + +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== + prompts@^2.0.1: version "2.4.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" @@ -4699,9 +4840,9 @@ prr@~1.0.1: integrity sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw== psl@^1.1.28, psl@^1.1.33: - version "1.8.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" - integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== + version "1.9.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== pstree.remy@^1.1.8: version "1.1.8" @@ -4755,12 +4896,17 @@ querystringify@^2.1.1: resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== +quick-format-unescaped@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7" + integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg== + range-parser@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -rc@^1.2.8: +rc@1.2.8, rc@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== @@ -4799,6 +4945,16 @@ readable-stream@1.1.14, readable-stream@^1.0.27-1: string_decoder "^1.1.1" util-deprecate "^1.0.1" +readable-stream@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.3.0.tgz#0914d0c72db03b316c9733bb3461d64a3cc50cba" + integrity sha512-MuEnA0lbSi7JS8XM+WNJlWZkHAAdm7gETHdFK//Q/mChGyj2akEFtdLZh32jSdkWGbRwCW9pn6g3LWDdDeZnBQ== + dependencies: + abort-controller "^3.0.0" + buffer "^6.0.3" + events "^3.3.0" + process "^0.11.10" + readable-stream@~0.0.2: version "0.0.4" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-0.0.4.tgz#f32d76e3fb863344a548d79923007173665b3b8d" @@ -4829,6 +4985,11 @@ readline-sync@^1.4.9: resolved "https://registry.yarnpkg.com/readline-sync/-/readline-sync-1.4.10.tgz#41df7fbb4b6312d673011594145705bf56d8873b" integrity sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw== +real-require@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78" + integrity sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg== + redis-commands@1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.7.0.tgz#15a6fea2d58281e27b1cd1acfb4b293e278c3a89" @@ -4853,17 +5014,17 @@ redlock@4.2.0: dependencies: bluebird "^3.7.2" -regenerator-runtime@^0.13.4: - version "0.13.9" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" - integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== +regenerator-runtime@^0.13.11: + version "0.13.11" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" + integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== registry-auth-token@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.1.tgz#6d7b4006441918972ccd5fedcd41dc322c79b250" - integrity sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw== + version "4.2.2" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.2.tgz#f02d49c3668884612ca031419491a13539e21fac" + integrity sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg== dependencies: - rc "^1.2.8" + rc "1.2.8" registry-url@^5.0.0: version "5.1.0" @@ -4931,11 +5092,11 @@ resolve.exports@^1.1.0: integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ== resolve@^1.20.0: - version "1.22.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" - integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== + version "1.22.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" + integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== dependencies: - is-core-module "^2.8.1" + is-core-module "^2.9.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" @@ -4963,6 +5124,11 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== +safe-stable-stringify@^2.3.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.2.tgz#ec7b037768098bf65310d1d64370de0dc02353aa" + integrity sha512-gMxvPJYhP0O9n2pvcfYfIuYgbledAOJFcqRThtPRmjscaipiwcwPPKLytpVzMkG2HAN87Qmo2d4PtGiri1dSLA== + safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -4983,6 +5149,11 @@ sax@>=0.1.1, sax@>=0.6.0: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== +secure-json-parse@^2.4.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-2.7.0.tgz#5a5f9cd6ae47df23dba3151edd06855d47e09862" + integrity sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw== + semver-diff@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-3.1.1.tgz#05f77ce59f325e00e2706afd67bb506ddb1ca32b" @@ -4990,13 +5161,20 @@ semver-diff@^3.1.1: dependencies: semver "^6.3.0" -semver@7.3.7, semver@7.x, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5: +semver@7.3.7: version "7.3.7" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== dependencies: lru-cache "^6.0.0" +semver@7.x, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.8: + version "7.3.8" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" + integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== + dependencies: + lru-cache "^6.0.0" + semver@^5.6.0, semver@^5.7.1: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" @@ -5058,6 +5236,20 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +sonic-boom@^2.1.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-2.8.0.tgz#c1def62a77425090e6ad7516aad8eb402e047611" + integrity sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg== + dependencies: + atomic-sleep "^1.0.0" + +sonic-boom@^3.0.0, sonic-boom@^3.1.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-3.2.1.tgz#972ceab831b5840a08a002fa95a672008bda1c38" + integrity sha512-iITeTHxy3B9FGu8aVdiDXUVAcHMF9Ss0cCsAOo2HfCrmVGT3/DT5oYaeu0M/YKZDlKTvChEyPq0zI9Hf33EX6A== + dependencies: + atomic-sleep "^1.0.0" + source-map-support@0.5.13: version "0.5.13" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" @@ -5088,6 +5280,11 @@ split2@^2.1.0: dependencies: through2 "^2.0.2" +split2@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/split2/-/split2-4.1.0.tgz#101907a24370f85bb782f08adaabe4e281ecf809" + integrity sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ== + sprintf-js@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673" @@ -5114,9 +5311,9 @@ sshpk@^1.7.0: tweetnacl "~0.14.0" stack-utils@^2.0.3: - version "2.0.5" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.5.tgz#d25265fca995154659dbbfba3b49254778d2fdd5" - integrity sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA== + version "2.0.6" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" + integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== dependencies: escape-string-regexp "^2.0.0" @@ -5235,9 +5432,9 @@ supports-color@^8.0.0: has-flag "^4.0.0" supports-hyperlinks@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz#4f77b42488765891774b70c79babd87f9bd594bb" - integrity sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ== + version "2.3.0" + resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz#3943544347c1ff90b15effb03fc14ae45ec10624" + integrity sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA== dependencies: has-flag "^4.0.0" supports-color "^7.0.0" @@ -5269,13 +5466,13 @@ tar-stream@^2.1.4: readable-stream "^3.1.1" tar@^6.1.11: - version "6.1.11" - resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" - integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA== + version "6.1.13" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.13.tgz#46e22529000f612180601a6fe0680e7da508847b" + integrity sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw== dependencies: chownr "^2.0.0" fs-minipass "^2.0.0" - minipass "^3.0.0" + minipass "^4.0.0" minizlib "^2.1.1" mkdirp "^1.0.3" yallist "^4.0.0" @@ -5297,6 +5494,13 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" +thread-stream@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-2.2.0.tgz#310c03a253f729094ce5d4638ef5186dfa80a9e8" + integrity sha512-rUkv4/fnb4rqy/gGy7VuqK6wE1+1DOCOWy4RMeaV69ZHMP11tQKZvZSip1yTgrKCMZzEMcCL/bKfHvSfDHx+iQ== + dependencies: + real-require "^0.2.0" + through2@3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.2.tgz#99f88931cfc761ec7678b41d5d7336b5b6a07bf4" @@ -5333,7 +5537,7 @@ tmpl@1.0.5: to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== to-readable-stream@^1.0.0: version "1.0.0" @@ -5359,16 +5563,7 @@ touch@^3.1.0: dependencies: nopt "~1.0.10" -"tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4" - integrity sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg== - dependencies: - psl "^1.1.33" - punycode "^2.1.1" - universalify "^0.1.2" - -tough-cookie@^4.1.2: +"tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.2.tgz#e53e84b85f24e0b65dd526f46628db6c85f6b874" integrity sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ== @@ -5389,7 +5584,7 @@ tough-cookie@~2.5.0: tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== ts-jest@28.0.4: version "28.0.4" @@ -5441,14 +5636,14 @@ tsscmp@1.0.6: tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== dependencies: safe-buffer "^5.0.1" tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== type-detect@4.0.8: version "4.0.8" @@ -5502,11 +5697,6 @@ unique-string@^2.0.0: dependencies: crypto-random-string "^2.0.0" -universalify@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== - universalify@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" @@ -5550,7 +5740,7 @@ uri-js@^4.2.2: url-parse-lax@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" - integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= + integrity sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ== dependencies: prepend-http "^2.0.0" @@ -5565,7 +5755,7 @@ url-parse@^1.5.3: url@0.10.3: version "0.10.3" resolved "https://registry.yarnpkg.com/url/-/url-0.10.3.tgz#021e4d9c7705f21bbf37d03ceb58767402774c64" - integrity sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ= + integrity sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ== dependencies: punycode "1.3.2" querystring "0.2.0" @@ -5573,12 +5763,12 @@ url@0.10.3: util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== utils-merge@1.x.x: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== uuid@3.3.2: version "3.3.2" @@ -5590,7 +5780,7 @@ uuid@8.1.0: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.1.0.tgz#6f1536eb43249f473abc6bd58ff983da1ca30d8d" integrity sha512-CI18flHDznR0lq54xBycOVmphdCYnQLKn8abKn7PXUiKUGdEd+/l9LWNJmugXel4hXq7S+RMNl34ecyC9TntWg== -uuid@8.3.2, uuid@^8.3.0, uuid@^8.3.2: +uuid@8.3.2, uuid@^8.3.0, uuid@^8.3.1, uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== @@ -5617,12 +5807,12 @@ v8-to-istanbul@^9.0.1: vary@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== dependencies: assert-plus "^1.0.0" core-util-is "1.0.2" @@ -5631,7 +5821,7 @@ verror@1.10.0: vuvuzela@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/vuvuzela/-/vuvuzela-1.0.3.tgz#3be145e58271c73ca55279dd851f12a682114b0b" - integrity sha1-O+FF5YJxxzylUnndhR8SpoIRSws= + integrity sha512-Tm7jR1xTzBbPW+6y1tknKiEhz04Wf/1iZkcTJjSFcpNko43+dFW6+OOeQe9taJIug3NdfUAjFKgUSyQrIKaDvQ== walker@^1.0.8: version "1.0.8" @@ -5643,7 +5833,7 @@ walker@^1.0.8: webfinger@^0.4.2: version "0.4.2" resolved "https://registry.yarnpkg.com/webfinger/-/webfinger-0.4.2.tgz#3477a6d97799461896039fcffc650b73468ee76d" - integrity sha1-NHem2XeZRhiWA5/P/GULc0aO520= + integrity sha512-PvvQ/k74HkC3q5G7bGu4VYeKDt3ePZMzT5qFPtEnOL8eyIU1/06OtDn9X5vlkQ23BlegA3eN89rDLiYUife3xQ== dependencies: step "0.0.x" xml2js "0.1.x" @@ -5651,12 +5841,12 @@ webfinger@^0.4.2: webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== whatwg-url@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== dependencies: tr46 "~0.0.3" webidl-conversions "^3.0.0" @@ -5694,7 +5884,7 @@ wrap-ansi@^7.0.0: wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== write-file-atomic@^3.0.0: version "3.0.3" @@ -5717,7 +5907,7 @@ write-file-atomic@^4.0.1: write-stream@~0.4.3: version "0.4.3" resolved "https://registry.yarnpkg.com/write-stream/-/write-stream-0.4.3.tgz#83cc8c0347d0af6057a93862b4e3ae01de5c81c1" - integrity sha1-g8yMA0fQr2BXqThitOOuAd5cgcE= + integrity sha512-IJrvkhbAnj89W/GAVdVgbnPiVw5Ntg/B4tc/MUCIEwj/g6JIww1DWJyB/yBMT3yw2/TkT6IUZ0+IYef3flEw8A== dependencies: readable-stream "~0.0.2" @@ -5729,7 +5919,7 @@ xdg-basedir@^4.0.0: xml2js@0.1.x: version "0.1.14" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.1.14.tgz#5274e67f5a64c5f92974cd85139e0332adc6b90c" - integrity sha1-UnTmf1pkxfkpdM2FE54DMq3GuQw= + integrity sha512-pbdws4PPPNc1HPluSUKamY4GWMk592K7qwcj6BExbVOhhubub8+pMda/ql68b6L3luZs/OGjGSB5goV7SnmgnA== dependencies: sax ">=0.1.1" @@ -5744,7 +5934,7 @@ xml2js@0.4.19: xmlbuilder@~9.0.1: version "9.0.7" resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" - integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0= + integrity sha512-7YXTQc3P2l9+0rjaUbLwMKRhtmwg1M1eDf6nag7urC7pIPYLD9W/jmzQ4ptRSUbodw5S0jfoGTflLemQibSpeQ== xtend@^4.0.2, xtend@~4.0.0, xtend@~4.0.1: version "4.0.2" @@ -5756,6 +5946,11 @@ y18n@^5.0.5: resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + yallist@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" @@ -5802,4 +5997,4 @@ yocto-queue@^0.1.0: zlib@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/zlib/-/zlib-1.0.5.tgz#6e7c972fc371c645a6afb03ab14769def114fcc0" - integrity sha1-bnyXL8NxxkWmr7A6sUdp3vEU/MA= + integrity sha512-40fpE2II+Cd3k8HWTWONfeKE2jL+P42iWJ1zzps5W51qcTsOUKM5Q5m2PFb0CLxlmFAaUuUdJGc3OfZy947v0w== diff --git a/packages/bbui/package.json b/packages/bbui/package.json index 3e8c7b4e66..2411b254cb 100644 --- a/packages/bbui/package.json +++ b/packages/bbui/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/bbui", "description": "A UI solution used in the different Budibase projects.", - "version": "2.2.26", + "version": "2.2.27-alpha.0", "license": "MPL-2.0", "svelte": "src/index.js", "module": "dist/bbui.es.js", @@ -38,7 +38,8 @@ ], "dependencies": { "@adobe/spectrum-css-workflow-icons": "1.2.1", - "@budibase/string-templates": "^2.2.26", + "@budibase/string-templates": "2.2.27-alpha.0", + "@spectrum-css/accordion": "3.0.24", "@spectrum-css/actionbutton": "1.0.1", "@spectrum-css/actiongroup": "1.0.1", "@spectrum-css/avatar": "3.0.2", diff --git a/packages/bbui/src/Accordion/Accordion.svelte b/packages/bbui/src/Accordion/Accordion.svelte new file mode 100644 index 0000000000..1c88450c9a --- /dev/null +++ b/packages/bbui/src/Accordion/Accordion.svelte @@ -0,0 +1,58 @@ + + +
+
+

+ + +

+
+ +
+
+
+ + diff --git a/packages/bbui/src/ActionButton/ActionButton.svelte b/packages/bbui/src/ActionButton/ActionButton.svelte index cfc810807e..663128160f 100644 --- a/packages/bbui/src/ActionButton/ActionButton.svelte +++ b/packages/bbui/src/ActionButton/ActionButton.svelte @@ -9,7 +9,6 @@ export let longPressable = false export let disabled = false export let icon = "" - export let dataCy = null export let size = "M" export let active = false export let fullWidth = false @@ -37,7 +36,6 @@ - {#if open} -
- {#if autocomplete} - (searchTerm = event.detail)} - {disabled} - placeholder="Search" - /> + {/if} + + + + (open = false)} + useAnchorWidth={!autoWidth} + maxWidth={autoWidth ? 400 : null} +> +
(open = false)} + > + {#if autocomplete} + (searchTerm = event.detail)} + {disabled} + placeholder="Search" + /> + {/if} +
    + {#if placeholderOption} +
  • onSelectOption(null)} + > + {placeholderOption} + +
  • {/if} -
      - {#if placeholderOption} + {#if filteredOptions.length} + {#each filteredOptions as option, idx}
    • onSelectOption(null)} + on:click={() => onSelectOption(getOptionValue(option, idx))} + class:is-disabled={!isOptionEnabled(option)} > - {placeholderOption} + {#if getOptionIcon(option, idx)} + + + + {/if} + {#if getOptionColour(option, idx)} + + + + {/if} + + {getOptionLabel(option, idx)} +
    • - {/if} - {#if filteredOptions.length} - {#each filteredOptions as option, idx} -
    • onSelectOption(getOptionValue(option, idx))} - class:is-disabled={!isOptionEnabled(option)} - > - {#if getOptionIcon(option, idx)} - - - - {/if} - {#if getOptionColour(option, idx)} - - - - {/if} - - {getOptionLabel(option, idx)} - - -
    • - {/each} - {/if} -
    -
- {/if} -
+ {/each} + {/if} + + + diff --git a/packages/bbui/src/Form/Core/Select.svelte b/packages/bbui/src/Form/Core/Select.svelte index 3e15b7f6ef..721083e3a6 100644 --- a/packages/bbui/src/Form/Core/Select.svelte +++ b/packages/bbui/src/Form/Core/Select.svelte @@ -18,8 +18,11 @@ export let autoWidth = false export let autocomplete = false export let sort = false + const dispatch = createEventDispatcher() + let open = false + $: fieldText = getFieldText(value, options, placeholder) $: fieldIcon = getFieldAttribute(getOptionIcon, value, options) $: fieldColour = getFieldAttribute(getOptionColour, value, options) diff --git a/packages/bbui/src/Form/Core/Switch.svelte b/packages/bbui/src/Form/Core/Switch.svelte index 9e45683382..ffbef6b27d 100644 --- a/packages/bbui/src/Form/Core/Switch.svelte +++ b/packages/bbui/src/Form/Core/Switch.svelte @@ -6,7 +6,6 @@ export let id = null export let text = null export let disabled = false - export let dataCy = null const dispatch = createEventDispatcher() const onChange = event => { @@ -16,7 +15,6 @@
diff --git a/packages/bbui/src/Form/EnvDropdown.svelte b/packages/bbui/src/Form/EnvDropdown.svelte new file mode 100644 index 0000000000..b5db23a870 --- /dev/null +++ b/packages/bbui/src/Form/EnvDropdown.svelte @@ -0,0 +1,50 @@ + + + + + diff --git a/packages/bbui/src/Form/Input.svelte b/packages/bbui/src/Form/Input.svelte index 251b23c86a..f37cf55b63 100644 --- a/packages/bbui/src/Form/Input.svelte +++ b/packages/bbui/src/Form/Input.svelte @@ -13,7 +13,6 @@ export let error = null export let updateOnChange = true export let quiet = false - export let dataCy export let autofocus const dispatch = createEventDispatcher() @@ -25,7 +24,6 @@ {} export let getSecondaryOptionIcon = () => {} export let quiet = false - export let dataCy export let autofocus export let primaryOptions = [] export let secondaryOptions = [] @@ -98,7 +97,6 @@ { @@ -19,5 +18,5 @@ - + diff --git a/packages/bbui/src/Icon/IconAvatar.svelte b/packages/bbui/src/Icon/IconAvatar.svelte index b404cdea9f..add51f5bdc 100644 --- a/packages/bbui/src/Icon/IconAvatar.svelte +++ b/packages/bbui/src/Icon/IconAvatar.svelte @@ -19,6 +19,7 @@ .icon { width: 28px; height: 28px; + flex: 0 0 28px; display: grid; place-items: center; border-radius: 50%; @@ -34,6 +35,7 @@ .icon.size--S { width: 22px; height: 22px; + flex: 0 0 22px; } .icon.size--S :global(.spectrum-Icon) { width: 16px; @@ -46,6 +48,7 @@ .icon.size--L { width: 40px; height: 40px; + flex: 0 0 40px; } .icon.size--L :global(.spectrum-Icon) { width: 28px; diff --git a/packages/bbui/src/InlineAlert/InlineAlert.svelte b/packages/bbui/src/InlineAlert/InlineAlert.svelte index 94ac6b2c2a..57e7296234 100644 --- a/packages/bbui/src/InlineAlert/InlineAlert.svelte +++ b/packages/bbui/src/InlineAlert/InlineAlert.svelte @@ -56,5 +56,6 @@ --spectrum-semantic-positive-icon-color: #2d9d78; --spectrum-semantic-negative-icon-color: #e34850; min-width: 100px; + margin: 0; } diff --git a/packages/bbui/src/Label/Label.svelte b/packages/bbui/src/Label/Label.svelte index 6b3392ce2d..ee6d9adf76 100644 --- a/packages/bbui/src/Label/Label.svelte +++ b/packages/bbui/src/Label/Label.svelte @@ -21,6 +21,7 @@ label { padding: 0; white-space: nowrap; + color: var(--spectrum-global-color-gray-600); } .muted { diff --git a/packages/bbui/src/Layout/Page.svelte b/packages/bbui/src/Layout/Page.svelte index 2996bcc613..01111fda9a 100644 --- a/packages/bbui/src/Layout/Page.svelte +++ b/packages/bbui/src/Layout/Page.svelte @@ -1,32 +1,101 @@ -
- +
+
+
+ +
+
+
+
{ + sidePanelVisble = false + }} + > + +
diff --git a/packages/bbui/src/Link/Link.svelte b/packages/bbui/src/Link/Link.svelte index 3bbfdd8282..ea9496ba72 100644 --- a/packages/bbui/src/Link/Link.svelte +++ b/packages/bbui/src/Link/Link.svelte @@ -1,5 +1,6 @@ dispatch("click") && e.stopPropagation()} {href} {target} {download} diff --git a/packages/bbui/src/List/ListItem.svelte b/packages/bbui/src/List/ListItem.svelte index 40d3c5541c..28015c4c57 100644 --- a/packages/bbui/src/List/ListItem.svelte +++ b/packages/bbui/src/List/ListItem.svelte @@ -30,9 +30,11 @@ {/if}
-
- -
+ {#if $$slots.default} +
+ +
+ {/if}
diff --git a/packages/bbui/src/Popover/Popover.svench b/packages/bbui/src/Popover/Popover.svench index 4d48d7f121..21ca0c66e8 100644 --- a/packages/bbui/src/Popover/Popover.svench +++ b/packages/bbui/src/Popover/Popover.svench @@ -29,7 +29,6 @@ font-size: var(--font-size-m); margin: 0 0 var(--spacing-l) 0; font-weight: 600; - font-family: var(--font-sans); } .input-group-column { diff --git a/packages/bbui/src/SideNavigation/Item.svelte b/packages/bbui/src/SideNavigation/Item.svelte index aa86fc02a8..dab88b05bc 100644 --- a/packages/bbui/src/SideNavigation/Item.svelte +++ b/packages/bbui/src/SideNavigation/Item.svelte @@ -8,7 +8,6 @@ export let icon = "" export let selected = false export let disabled = false - export let dataCy export let badge = "" @@ -17,7 +16,6 @@ class:is-selected={selected} class:is-disabled={disabled} on:click - data-cy={dataCy} > {#if heading}
{:else} -
+
{#if fields.length}
{#if showEditColumn} @@ -356,7 +374,7 @@ {/if} {#if sortedRows?.length} {#each sortedRows as row, idx} -
+
{#if showEditColumn}
diff --git a/packages/bbui/src/Tags/Tag.svelte b/packages/bbui/src/Tags/Tag.svelte index f7089decdb..0cdd6c385d 100644 --- a/packages/bbui/src/Tags/Tag.svelte +++ b/packages/bbui/src/Tags/Tag.svelte @@ -37,7 +37,7 @@ diff --git a/packages/bbui/src/Tags/Tags.svelte b/packages/bbui/src/Tags/Tags.svelte index 36d34507f3..ebca64b774 100644 --- a/packages/bbui/src/Tags/Tags.svelte +++ b/packages/bbui/src/Tags/Tags.svelte @@ -5,3 +5,13 @@
+ + diff --git a/packages/bbui/src/Typography/Heading.svelte b/packages/bbui/src/Typography/Heading.svelte index 077c0a4878..5f243ad5a6 100644 --- a/packages/bbui/src/Typography/Heading.svelte +++ b/packages/bbui/src/Typography/Heading.svelte @@ -15,3 +15,9 @@ > + + diff --git a/packages/bbui/src/bbui.css b/packages/bbui/src/bbui.css index f98f27bf58..ef3483d3df 100644 --- a/packages/bbui/src/bbui.css +++ b/packages/bbui/src/bbui.css @@ -40,12 +40,14 @@ --rounded-medium: 8px; --rounded-large: 16px; - --font-sans: Source Sans Pro, -apple-system, BlinkMacSystemFont, Segoe UI, "Inter", - "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", - "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + --font-sans: "Source Sans Pro", -apple-system, BlinkMacSystemFont, Segoe UI, "Inter", + "Helvetica Neue", Arial, "Noto Sans", sans-serif; + --font-accent: "Source Sans Pro", -apple-system, BlinkMacSystemFont, Segoe UI, "Inter", + "Helvetica Neue", Arial, "Noto Sans", sans-serif; --font-serif: "Georgia", Cambria, Times New Roman, Times, serif; --font-mono: Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + --spectrum-alias-body-text-font-family: var(--font-sans); font-size: 16px; --font-size-xs: 0.75rem; @@ -89,6 +91,8 @@ --border-light-2: 2px var(--grey-3) solid; --border-blue: 2px var(--blue) solid; --border-transparent: 2px transparent solid; + + --spectrum-alias-text-color-disabled: var(--spectrum-global-color-gray-600); } a { diff --git a/packages/bbui/src/context.js b/packages/bbui/src/context.js index bb95f8b425..919f2140d6 100644 --- a/packages/bbui/src/context.js +++ b/packages/bbui/src/context.js @@ -1,3 +1,4 @@ export default { Modal: "bbui-modal", + PopoverRoot: "bbui-popover-root", } diff --git a/packages/bbui/src/index.js b/packages/bbui/src/index.js index 601c4dcbca..482226ed88 100644 --- a/packages/bbui/src/index.js +++ b/packages/bbui/src/index.js @@ -27,6 +27,7 @@ export { default as RadioGroup } from "./Form/RadioGroup.svelte" export { default as Checkbox } from "./Form/Checkbox.svelte" export { default as InputDropdown } from "./Form/InputDropdown.svelte" export { default as PickerDropdown } from "./Form/PickerDropdown.svelte" +export { default as EnvDropdown } from "./Form/EnvDropdown.svelte" export { default as DetailSummary } from "./DetailSummary/DetailSummary.svelte" export { default as Popover } from "./Popover/Popover.svelte" export { default as ProgressBar } from "./ProgressBar/ProgressBar.svelte" @@ -75,6 +76,7 @@ export { default as ListItem } from "./List/ListItem.svelte" export { default as IconSideNav } from "./IconSideNav/IconSideNav.svelte" export { default as IconSideNavItem } from "./IconSideNav/IconSideNavItem.svelte" export { default as Slider } from "./Form/Slider.svelte" +export { default as Accordion } from "./Accordion/Accordion.svelte" // Renderers export { default as BoldRenderer } from "./Table/BoldRenderer.svelte" @@ -101,3 +103,6 @@ export { banner, BANNER_TYPES } from "./Stores/banner" // Helpers export * as Helpers from "./helpers" + +// Fancy form components +export * from "./FancyForm" diff --git a/packages/bbui/yarn.lock b/packages/bbui/yarn.lock index 4263188530..16f1feb920 100644 --- a/packages/bbui/yarn.lock +++ b/packages/bbui/yarn.lock @@ -2,7 +2,7 @@ # yarn lockfile v1 -"@adobe/spectrum-css-workflow-icons@^1.2.1": +"@adobe/spectrum-css-workflow-icons@1.2.1": version "1.2.1" resolved "https://registry.yarnpkg.com/@adobe/spectrum-css-workflow-icons/-/spectrum-css-workflow-icons-1.2.1.tgz#7e2cb3fcfb5c8b12d7275afafbb6ec44913551b4" integrity sha512-uVgekyBXnOVkxp+CUssjN/gefARtudZC8duEn1vm0lBQFwGRZFlDEzU1QC+aIRWCrD1Z8OgRpmBYlSZ7QS003w== @@ -109,6 +109,11 @@ estree-walker "^1.0.1" picomatch "^2.2.2" +"@spectrum-css/accordion@3.0.24": + version "3.0.24" + resolved "https://registry.yarnpkg.com/@spectrum-css/accordion/-/accordion-3.0.24.tgz#f89066c120c57b0cfc9aba66d60c39fc1cf69f74" + integrity sha512-jNOmUsxmiT3lRLButnN5KKHM94fd+87fjiF8L0c4uRNgJl6ZsBuxPXrM15lV4y1f8D2IACAw01/ZkGRAeaCOFA== + "@spectrum-css/actionbutton@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@spectrum-css/actionbutton/-/actionbutton-1.0.1.tgz#9c75da37ea6915919fb574c74bd60dacc03b6577" @@ -1549,9 +1554,9 @@ json-parse-even-better-errors@^2.3.0: integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== json5@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + version "1.0.2" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" + integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== dependencies: minimist "^1.2.0" @@ -1662,16 +1667,11 @@ minimatch@^3.0.4: dependencies: brace-expansion "^1.1.7" -minimist@^1.2.0: +minimist@^1.2.0, minimist@^1.2.5: version "1.2.7" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== -minimist@^1.2.5: - version "1.2.6" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" - integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== - mkdirp@~0.5.1: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" diff --git a/packages/builder/assets/bb-emblem.svg b/packages/builder/assets/bb-emblem.svg index 9f4f3690d5..7d499e4862 100644 --- a/packages/builder/assets/bb-emblem.svg +++ b/packages/builder/assets/bb-emblem.svg @@ -3,7 +3,7 @@ diff --git a/packages/builder/cypress.json b/packages/builder/cypress.json deleted file mode 100644 index f1eada481f..0000000000 --- a/packages/builder/cypress.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "baseUrl": "http://localhost:4100", - "video": true, - "projectId": "bmbemn", - "reporter": "cypress-multi-reporters", - "reporterOptions": { - "configFile": "reporterConfig.json" - }, - "env": { - "PORT": "4100", - "WORKER_PORT": "4200", - "JWT_SECRET": "test", - "HOST_IP": "" - }, - "retries": { - "runMode": 1, - "openMode": 0 - } -} \ No newline at end of file diff --git a/packages/builder/cypress/fixtures/apikey.json b/packages/builder/cypress/fixtures/apikey.json deleted file mode 100644 index 1def14ed6c..0000000000 --- a/packages/builder/cypress/fixtures/apikey.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "budibase": "CB373643-3FC4-4902-9E31-449C0ED066B6" -} \ No newline at end of file diff --git a/packages/builder/cypress/fixtures/example.json b/packages/builder/cypress/fixtures/example.json deleted file mode 100644 index da18d9352a..0000000000 --- a/packages/builder/cypress/fixtures/example.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "Using fixtures to represent data", - "email": "hello@cypress.io", - "body": "Fixtures are a great way to mock data for responses to routes" -} \ No newline at end of file diff --git a/packages/builder/cypress/fixtures/exported-app.txt b/packages/builder/cypress/fixtures/exported-app.txt deleted file mode 100644 index 28aeaf958a..0000000000 --- a/packages/builder/cypress/fixtures/exported-app.txt +++ /dev/null @@ -1,3 +0,0 @@ -{"version":"1.2.9","db_type":"http","start_time":"2022-05-12T13:47:50.453Z","db_info":{"db_name":"app_dev_7cae7fa4db8745da848f91430a8211bf","purge_seq":"0-g1AAAABXeJzLYWBgYMpgTmEQTM4vTc5ISXIwNDLXMwBCwxyQVB4LkGRoAFL_gSArkQGP2kSGpHqIoiwAtOgYRA","update_seq":"11-g1AAAACbeJzLYWBgYMpgTmEQTM4vTc5ISXIwNDLXMwBCwxyQVB4LkGRoAFL_gSArgzmRPRcowJ5klmZgaZmKTR8e0xIZkuqhxrBAjEk0NzcwMsSmIQsA89QoWg","sizes":{"file":94626,"external":5665,"active":7627},"props":{},"doc_del_count":0,"doc_count":7,"disk_format_version":8,"compact_running":false,"cluster":{"q":2,"n":1,"w":1,"r":1},"instance_start_time":"0","host":"http://localhost:4005/app_dev_7cae7fa4db8745da848f91430a8211bf/","auto_compaction":false,"adapter":"http"}} -{"docs":[{"_id":"_design/database","_rev":"4-ad6d41ef604ab34da380438c1be89521","views":{"by_link":{"map":"function (doc) {\n // everything in this must remain constant as its going to Pouch, no external variables\n if (doc.type === \"link\") {\n let doc1 = doc.doc1;\n let doc2 = doc.doc2;\n // eslint-disable-next-line no-undef\n emit([doc1.tableId, doc1.rowId], {\n id: doc2.rowId,\n thisId: doc1.rowId,\n fieldName: doc1.fieldName,\n });\n // if linking to same table can't emit twice\n if (doc1.tableId !== doc2.tableId) {\n // eslint-disable-next-line no-undef\n emit([doc2.tableId, doc2.rowId], {\n id: doc1.rowId,\n thisId: doc2.rowId,\n fieldName: doc2.fieldName,\n });\n }\n }\n }"},"screen_routes":{"map":"function(doc) {\n if (doc._id.startsWith(\"screen_\")) {\n emit(doc._id, {\n id: doc._id,\n routing: doc.routing,\n })\n }\n }"}},"indexes":{"rows":{"index":"function (doc) {\n function idx(input, prev) {\n for (let key of Object.keys(input)) {\n let idxKey = prev != null ? `${prev}.${key}` : key;\n idxKey = idxKey.replace(/ /g, \"_\");\n if (Array.isArray(input[key])) {\n for (let val of input[key]) {\n if (typeof val !== \"object\") {\n // eslint-disable-next-line no-undef\n index(idxKey, val, { store: true });\n }\n }\n }\n else if (key === \"_id\" || key === \"_rev\" || input[key] == null) {\n continue;\n }\n if (typeof input[key] === \"string\") {\n // eslint-disable-next-line no-undef\n index(idxKey, input[key].toLowerCase(), { store: true });\n }\n else if (typeof input[key] !== \"object\") {\n // eslint-disable-next-line no-undef\n index(idxKey, input[key], { store: true });\n }\n else {\n idx(input[key], idxKey);\n }\n }\n }\n if (doc._id.startsWith(\"ro_\")) {\n // eslint-disable-next-line no-undef\n index(\"default\", doc._id);\n idx(doc);\n }\n }","analyzer":"keyword"}},"_revisions":{"start":4,"ids":["ad6d41ef604ab34da380438c1be89521","cb47f4fd824d5e096ac8b76117e6f93d","68a9a1d1b01b327676ecbaa4b1e5b8a7","0b24e44a44af45e51e562fd124ce3007"]}},{"_id":"app_metadata","_rev":"2-a4fe55378bfec0fc71e58a1364ac9965","appId":"app_dev_7cae7fa4db8745da848f91430a8211bf","type":"app","version":"1.0.155-alpha.0","componentLibraries":["@budibase/standard-components"],"name":"My app","url":"/my-app","instance":{"_id":"app_dev_7cae7fa4db8745da848f91430a8211bf"},"tenantId":"default","updatedAt":"2022-05-12T13:47:28.756Z","createdAt":"2022-05-12T13:47:26.825Z","status":"development","_revisions":{"start":2,"ids":["a4fe55378bfec0fc71e58a1364ac9965","f0d06bdb6e6ae4781eb5c4aa224002ff"]}},{"_id":"layout_private_master","_rev":"1-c02411b58d697e38763889a375d52159","componentLibraries":["@budibase/standard-components"],"title":"My app","favicon":"./_shared/favicon.png","stylesheets":[],"name":"Navigation Layout","props":{"_id":"4f569166-a4f3-47ea-a09e-6d218c75586f","_instanceName":"Navigation Layout","_component":"@budibase/standard-components/layout","_children":[{"_id":"7fcf11e4-6f5b-4085-8e0d-9f3d44c98967","_component":"@budibase/standard-components/screenslot","_instanceName":"Screen slot","_styles":{"normal":{"flex":"1 1 auto","display":"flex","flex-direction":"column","justify-content":"flex-start","align-items":"stretch"},"hover":{},"active":{},"selected":{}},"_children":[]}],"_styles":{"active":{},"hover":{},"normal":{},"selected":{}},"title":"My app","navigation":"Top","width":"Large","links":[{"text":"Home","url":"/"}]}},{"_id":"layout_public_master","_rev":"1-d6bce47046d4d0de4f19a6ff95064109","componentLibraries":["@budibase/standard-components"],"title":"My app","favicon":"./_shared/favicon.png","stylesheets":[],"name":"Empty Layout","props":{"_id":"3723ffa1-f9e0-4c05-8013-98195c788ed6","_instanceName":"Empty Layout","_component":"@budibase/standard-components/layout","_children":[{"_id":"7fcf11e4-6f5b-4085-8e0d-9f3d44c98967","_component":"@budibase/standard-components/screenslot","_instanceName":"Screen slot","_styles":{"normal":{"flex":"1 1 auto","display":"flex","flex-direction":"column","justify-content":"flex-start","align-items":"stretch"},"hover":{},"active":{},"selected":{}},"_children":[]}],"_styles":{"active":{},"hover":{},"normal":{},"selected":{}},"navigation":"None","width":"Large","links":[{"text":"Home","url":"/"}]}},{"_id":"screen_b19c454fa5ae41ab874a8860623ab37c","_rev":"1-02dddd460ad14de50dc885aa362452c6","layoutId":"layout_private_master","props":{"_id":"c87457efbc05a43f39064d9dacc9d4b67","_component":"@budibase/standard-components/container","_styles":{"normal":{},"hover":{},"active":{},"selected":{}},"_children":[],"_instanceName":"New Screen","direction":"column","hAlign":"stretch","vAlign":"top","size":"grow","gap":"M"},"routing":{"route":"/home","roleId":"BASIC","roldId":"BASIC"},"name":"screen-id"},{"_id":"ta_users","_rev":"1-30a4344f056c24cf776d5736eb3c7ed5","type":"table","views":{},"name":"Users","schema":{"email":{"type":"string","constraints":{"type":"string","email":true,"length":{"maximum":""},"presence":true},"fieldName":"email","name":"email"},"firstName":{"name":"firstName","fieldName":"firstName","type":"string","constraints":{"type":"string","presence":false}},"lastName":{"name":"lastName","fieldName":"lastName","type":"string","constraints":{"type":"string","presence":false}},"roleId":{"fieldName":"roleId","name":"roleId","type":"options","constraints":{"type":"string","presence":false,"inclusion":["ADMIN","POWER","BASIC","PUBLIC"]}},"status":{"fieldName":"status","name":"status","type":"options","constraints":{"type":"string","presence":false,"inclusion":["active","inactive"]}}},"primaryDisplay":"email"}]} -{"seq":"11-g1AAAACbeJzLYWBgYMpgTmEQTM4vTc5ISXIwNDLXMwBCwxyQVCJDUv3___-zMpgTWXKBAuxJiebmBkaG2DTgMSaPBUgyNACp_1DT2CGmmaUZWFqmYtOXBQAWQiha"} diff --git a/packages/builder/cypress/fixtures/profile.json b/packages/builder/cypress/fixtures/profile.json deleted file mode 100644 index b6c355ca5c..0000000000 --- a/packages/builder/cypress/fixtures/profile.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "id": 8739, - "name": "Jane", - "email": "jane@example.com" -} \ No newline at end of file diff --git a/packages/builder/cypress/fixtures/users.json b/packages/builder/cypress/fixtures/users.json deleted file mode 100644 index f82fc8dfb2..0000000000 --- a/packages/builder/cypress/fixtures/users.json +++ /dev/null @@ -1,232 +0,0 @@ -[ - { - "id": 1, - "name": "Leanne Graham", - "username": "Bret", - "email": "Sincere@april.biz", - "address": { - "street": "Kulas Light", - "suite": "Apt. 556", - "city": "Gwenborough", - "zipcode": "92998-3874", - "geo": { - "lat": "-37.3159", - "lng": "81.1496" - } - }, - "phone": "1-770-736-8031 x56442", - "website": "hildegard.org", - "company": { - "name": "Romaguera-Crona", - "catchPhrase": "Multi-layered client-server neural-net", - "bs": "harness real-time e-markets" - } - }, - { - "id": 2, - "name": "Ervin Howell", - "username": "Antonette", - "email": "Shanna@melissa.tv", - "address": { - "street": "Victor Plains", - "suite": "Suite 879", - "city": "Wisokyburgh", - "zipcode": "90566-7771", - "geo": { - "lat": "-43.9509", - "lng": "-34.4618" - } - }, - "phone": "010-692-6593 x09125", - "website": "anastasia.net", - "company": { - "name": "Deckow-Crist", - "catchPhrase": "Proactive didactic contingency", - "bs": "synergize scalable supply-chains" - } - }, - { - "id": 3, - "name": "Clementine Bauch", - "username": "Samantha", - "email": "Nathan@yesenia.net", - "address": { - "street": "Douglas Extension", - "suite": "Suite 847", - "city": "McKenziehaven", - "zipcode": "59590-4157", - "geo": { - "lat": "-68.6102", - "lng": "-47.0653" - } - }, - "phone": "1-463-123-4447", - "website": "ramiro.info", - "company": { - "name": "Romaguera-Jacobson", - "catchPhrase": "Face to face bifurcated interface", - "bs": "e-enable strategic applications" - } - }, - { - "id": 4, - "name": "Patricia Lebsack", - "username": "Karianne", - "email": "Julianne.OConner@kory.org", - "address": { - "street": "Hoeger Mall", - "suite": "Apt. 692", - "city": "South Elvis", - "zipcode": "53919-4257", - "geo": { - "lat": "29.4572", - "lng": "-164.2990" - } - }, - "phone": "493-170-9623 x156", - "website": "kale.biz", - "company": { - "name": "Robel-Corkery", - "catchPhrase": "Multi-tiered zero tolerance productivity", - "bs": "transition cutting-edge web services" - } - }, - { - "id": 5, - "name": "Chelsey Dietrich", - "username": "Kamren", - "email": "Lucio_Hettinger@annie.ca", - "address": { - "street": "Skiles Walks", - "suite": "Suite 351", - "city": "Roscoeview", - "zipcode": "33263", - "geo": { - "lat": "-31.8129", - "lng": "62.5342" - } - }, - "phone": "(254)954-1289", - "website": "demarco.info", - "company": { - "name": "Keebler LLC", - "catchPhrase": "User-centric fault-tolerant solution", - "bs": "revolutionize end-to-end systems" - } - }, - { - "id": 6, - "name": "Mrs. Dennis Schulist", - "username": "Leopoldo_Corkery", - "email": "Karley_Dach@jasper.info", - "address": { - "street": "Norberto Crossing", - "suite": "Apt. 950", - "city": "South Christy", - "zipcode": "23505-1337", - "geo": { - "lat": "-71.4197", - "lng": "71.7478" - } - }, - "phone": "1-477-935-8478 x6430", - "website": "ola.org", - "company": { - "name": "Considine-Lockman", - "catchPhrase": "Synchronised bottom-line interface", - "bs": "e-enable innovative applications" - } - }, - { - "id": 7, - "name": "Kurtis Weissnat", - "username": "Elwyn.Skiles", - "email": "Telly.Hoeger@billy.biz", - "address": { - "street": "Rex Trail", - "suite": "Suite 280", - "city": "Howemouth", - "zipcode": "58804-1099", - "geo": { - "lat": "24.8918", - "lng": "21.8984" - } - }, - "phone": "210.067.6132", - "website": "elvis.io", - "company": { - "name": "Johns Group", - "catchPhrase": "Configurable multimedia task-force", - "bs": "generate enterprise e-tailers" - } - }, - { - "id": 8, - "name": "Nicholas Runolfsdottir V", - "username": "Maxime_Nienow", - "email": "Sherwood@rosamond.me", - "address": { - "street": "Ellsworth Summit", - "suite": "Suite 729", - "city": "Aliyaview", - "zipcode": "45169", - "geo": { - "lat": "-14.3990", - "lng": "-120.7677" - } - }, - "phone": "586.493.6943 x140", - "website": "jacynthe.com", - "company": { - "name": "Abernathy Group", - "catchPhrase": "Implemented secondary concept", - "bs": "e-enable extensible e-tailers" - } - }, - { - "id": 9, - "name": "Glenna Reichert", - "username": "Delphine", - "email": "Chaim_McDermott@dana.io", - "address": { - "street": "Dayna Park", - "suite": "Suite 449", - "city": "Bartholomebury", - "zipcode": "76495-3109", - "geo": { - "lat": "24.6463", - "lng": "-168.8889" - } - }, - "phone": "(775)976-6794 x41206", - "website": "conrad.com", - "company": { - "name": "Yost and Sons", - "catchPhrase": "Switchable contextually-based project", - "bs": "aggregate real-time technologies" - } - }, - { - "id": 10, - "name": "Clementina DuBuque", - "username": "Moriah.Stanton", - "email": "Rey.Padberg@karina.biz", - "address": { - "street": "Kattie Turnpike", - "suite": "Suite 198", - "city": "Lebsackbury", - "zipcode": "31428-2261", - "geo": { - "lat": "-38.2386", - "lng": "57.2232" - } - }, - "phone": "024-648-3804", - "website": "ambrose.net", - "company": { - "name": "Hoeger LLC", - "catchPhrase": "Centralized empowering task-force", - "bs": "target end-to-end tables" - } - } -] \ No newline at end of file diff --git a/packages/builder/cypress/integration/addMultiOptionDatatype.spec.js b/packages/builder/cypress/integration/addMultiOptionDatatype.spec.js deleted file mode 100644 index f844402958..0000000000 --- a/packages/builder/cypress/integration/addMultiOptionDatatype.spec.js +++ /dev/null @@ -1,45 +0,0 @@ -import filterTests from "../support/filterTests" -const interact = require('../support/interact') - -filterTests(['all'], () => { - xcontext("Add Multi-Option Datatype", () => { - before(() => { - cy.login() - cy.createTestApp() - }) - - it("should create a new table, with data", () => { - cy.createTable("Multi Data") - cy.addColumn("Multi Data", "Test Data", "Multi-select", "1\n2\n3\n4\n5") - cy.addRowMultiValue(["1", "2", "3", "4", "5"]) - }) - - it("should add form with multi select picker, containing 5 options", () => { - cy.navigateToFrontend() - // Add data provider - cy.searchAndAddComponent("Data Provider") - cy.get(interact.DATASOURCE_PROP_CONTROL).click() - cy.get(interact.DROPDOWN).contains("Multi Data").click() - // Add Form with schema to match table - cy.searchAndAddComponent("Form") - cy.get(interact.DATASOURCE_PROP_CONTROL).click() - cy.get(interact.DROPDOWN).contains("Multi Data").click() - // Add multi-select picker to form - cy.searchAndAddComponent("Multi-select Picker").then(componentId => { - cy.get(interact.DATASOURCE_FIELD_CONTROL).type("Test Data").type("{enter}") - cy.wait(1000) - cy.getComponent(componentId).contains("Choose some options").click() - // Check picker has 5 items - cy.getComponent(componentId).find("li").should("have.length", 5) - // Select all items - for (let i = 1; i < 6; i++) { - cy.getComponent(componentId).find("li").contains(i).click() - } - // Check items have been selected - cy.getComponent(componentId) - .find(interact.SPECTRUM_PICKER_LABEL) - .contains("(5)") - }) - }) - }) -}) diff --git a/packages/builder/cypress/integration/addRadioButtons.spec.js b/packages/builder/cypress/integration/addRadioButtons.spec.js deleted file mode 100644 index 3e344c3656..0000000000 --- a/packages/builder/cypress/integration/addRadioButtons.spec.js +++ /dev/null @@ -1,43 +0,0 @@ -import filterTests from "../support/filterTests" -const interact = require('../support/interact') - -filterTests(['all'], () => { - xcontext("Add Radio Buttons", () => { - before(() => { - cy.login() - cy.createTestApp() - }) - - it("should add Radio Buttons options picker on form, add data, and confirm", () => { - cy.navigateToFrontend() - cy.searchAndAddComponent("Form") - cy.searchAndAddComponent("Options Picker").then((componentId) => { - // Provide field setting - cy.get(interact.DATASOURCE_FIELD_CONTROL).type("1") - // Open dropdown and select Radio buttons - cy.get(interact.OPTION_TYPE_PROP_CONTROL).click().then(() => { - cy.get(interact.SPECTRUM_POPOVER).contains('Radio buttons') - .click() - }) - const radioButtonsTotal = 3 - // Add values and confirm total - addRadioButtonData(radioButtonsTotal) - cy.getComponent(componentId).find('[type="radio"]') - .should('have.length', radioButtonsTotal) - }) - }) - - const addRadioButtonData = (totalRadioButtons) => { - cy.get(interact.OPTION_SOURCE_PROP_CONROL).click().then(() => { - cy.get(interact.SPECTRUM_POPOVER).contains('Custom') - .click() - .wait(1000) - }) - cy.addCustomSourceOptions(totalRadioButtons) - } - - after(() => { - cy.deleteAllApps() - }) - }) -}) diff --git a/packages/builder/cypress/integration/adminAndManagement/accountPortals.spec.js b/packages/builder/cypress/integration/adminAndManagement/accountPortals.spec.js deleted file mode 100644 index 448240f81d..0000000000 --- a/packages/builder/cypress/integration/adminAndManagement/accountPortals.spec.js +++ /dev/null @@ -1,116 +0,0 @@ -import filterTests from "../../support/filterTests" -const interact = require('../../support/interact') - -filterTests(["smoke", "all"], () => { - context("Account Portals", () => { - - const bbUserEmail = "bbuser@test.com" - - before(() => { - cy.login() - cy.deleteApp("Cypress Tests") - cy.createApp("Cypress Tests", false) - - // Create new user - cy.wait(500) - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000}) - cy.createUser(bbUserEmail) - cy.contains("bbuser").click() - cy.wait(500) - - // Reset password - cy.get(".title").within(() => { - cy.get(interact.SPECTRUM_ICON).click({ force: true }) - }) - cy.get(interact.SPECTRUM_MENU).within(() => { - cy.get(interact.SPECTRUM_MENU_ITEM).contains("Force password reset").click({ force: true }) - }) - - cy.get(interact.SPECTRUM_DIALOG_GRID) - .find(interact.SPECTRUM_TEXTFIELD_INPUT).invoke('val').as('pwd') - - cy.get(interact.SPECTRUM_BUTTON).contains("Reset password").click({ force: true }) - - // Login as new user and set password - cy.logOut() - cy.get('@pwd').then((pwd) => { - cy.login(bbUserEmail, pwd) - }) - - for (let i = 0; i < 2; i++) { - cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).eq(i).type("test") - } - cy.get(interact.SPECTRUM_BUTTON).contains("Reset your password").click({ force: true }) - //cy.logoutNoAppGrid() - }) - - it("should verify Standard Portal", () => { - // Development access should be disabled (Admin access is already disabled) - cy.login() - cy.setUserRole("bbuser", "App User") - bbUserLogin() - - // Verify Standard Portal - cy.get(interact.SPECTRUM_SIDENAV).should('not.exist') // No config sections - cy.get(interact.CREATE_APP_BUTTON).should('not.exist') // No create app button - cy.get(".app").should('not.exist') // No apps -> no roles assigned to user - cy.get(interact.CONTAINER).should('contain', bbUserEmail) // Message containing users email - - cy.logoutNoAppGrid() - }) - - it("should verify Admin Portal", () => { - cy.login() - // Configure user role - cy.setUserRole("bbuser", "Admin") - bbUserLogin() - - // Verify available options for Admin portal - cy.get(interact.SPECTRUM_SIDENAV) - .should('contain', 'Apps') - //.and('contain', 'Usage') - .and('contain', 'Users') - .and('contain', 'Auth') - .and('contain', 'Email') - .and('contain', 'Organisation') - .and('contain', 'Theming') - .and('contain', 'Update') - //.and('contain', 'Upgrade') - - cy.logOut() - }) - - it("should verify Development Portal", () => { - // Only Development access should be enabled - cy.login() - cy.setUserRole("bbuser", "Developer") - bbUserLogin() - - // Verify available options for Admin portal - cy.get(interact.SPECTRUM_SIDENAV) - .should('contain', 'Apps') - //.and('contain', 'Usage') - .and('not.contain', 'Users') - .and('not.contain', 'Auth') - .and('not.contain', 'Email') - .and('not.contain', 'Organisation') - .and('contain', 'Theming') - .and('not.contain', 'Update') - .and('not.contain', 'Upgrade') - - cy.logOut() - }) - - const bbUserLogin = () => { - // Login as bbuser - cy.logOut() - cy.login(bbUserEmail, "test") - } - - after(() => { - cy.login() - // Delete BB user - cy.deleteUser(bbUserEmail) - }) - }) -}) diff --git a/packages/builder/cypress/integration/adminAndManagement/authentication.spec.js b/packages/builder/cypress/integration/adminAndManagement/authentication.spec.js deleted file mode 100644 index 5cc42cb59a..0000000000 --- a/packages/builder/cypress/integration/adminAndManagement/authentication.spec.js +++ /dev/null @@ -1,178 +0,0 @@ -import filterTests from "../../support/filterTests" -// const interact = require("../support/interact") - -filterTests(["smoke", "all"], () => { - context("Auth Configuration", () => { - before(() => { - cy.login() - }) - - after(() => { - cy.get(".spectrum-SideNav li").contains("Auth").click() - cy.location().should(loc => { - expect(loc.pathname).to.eq("/builder/portal/manage/auth") - }) - - cy.get("[data-cy=new-scope-input]").clear() - - cy.get("div.content").scrollTo("bottom") - cy.get("[data-cy=oidc-active]").click() - - cy.get("[data-cy=oidc-active]").should('not.be.checked') - - cy.intercept("POST", "/api/global/configs").as("updateAuth") - cy.get("button[data-cy=oidc-save]").contains("Save").click({force: true}) - cy.wait("@updateAuth") - cy.get("@updateAuth").its("response.statusCode").should("eq", 200) - - cy.get(".spectrum-Toast-content") - .contains("Settings saved") - .should("be.visible") - }) - - it("Should allow updating of the OIDC config", () => { - cy.get(".spectrum-SideNav li").contains("Auth").click() - cy.location().should(loc => { - expect(loc.pathname).to.eq("/builder/portal/manage/auth") - }) - cy.get("div.content").scrollTo("bottom") - cy.get(".spectrum-Toast .spectrum-ClearButton").click() - - cy.get("input[data-cy=configUrl]").type("http://budi-auth.com/v2") - cy.get("input[data-cy=clientID]").type("34ac6a13-f24a-4b52-c70d-fa544ffd11b2") - cy.get("input[data-cy=clientSecret]").type("12A8Q~4nS_DWhOOJ2vWIRsNyDVsdtXPD.Zxa9df_") - - cy.get("button[data-cy=oidc-save]").should("not.be.disabled"); - - cy.intercept("POST", "/api/global/configs").as("updateAuth") - cy.get("button[data-cy=oidc-save]").contains("Save").click({force: true}) - cy.wait("@updateAuth") - cy.get("@updateAuth").its("response.statusCode").should("eq", 200) - - cy.get(".spectrum-Toast-content") - .contains("Settings saved") - .should("be.visible") - }) - - it("Should display default scopes in advanced config.", () => { - cy.get(".spectrum-SideNav li").contains("Auth").click() - cy.location().should(loc => { - expect(loc.pathname).to.eq("/builder/portal/manage/auth") - }) - cy.get("div.content").scrollTo("bottom") - - cy.get(".spectrum-Tags").find(".spectrum-Tags-item").its("length").should("eq", 4) - - cy.get(".spectrum-Tags-item").contains("openid") - cy.get(".spectrum-Tags-item").contains("openid").find(".spectrum-ClearButton").should("not.exist") - - cy.get(".spectrum-Tags-item").contains("offline_access") - cy.get(".spectrum-Tags-item").contains("email") - cy.get(".spectrum-Tags-item").contains("profile") - }) - - it("Add a new scopes", () => { - cy.get(".spectrum-SideNav li").contains("Auth").click() - cy.location().should(loc => { - expect(loc.pathname).to.eq("/builder/portal/manage/auth") - }) - cy.get("div.content").scrollTo("bottom") - - cy.get("[data-cy=new-scope-input]").type("Sample{enter}") - cy.get(".spectrum-Tags").find(".spectrum-Tags-item").its("length").should("eq", 5) - cy.get(".spectrum-Tags-item").contains("Sample") - - cy.get(".auth-form input.spectrum-Textfield-input").type("Another ") - cy.get(".spectrum-Tags").find(".spectrum-Tags-item").its("length").should("eq", 6) - cy.get(".spectrum-Tags-item").contains("Another") - - cy.get("button[data-cy=oidc-save]").should("not.be.disabled"); - - cy.intercept("POST", "/api/global/configs").as("updateAuth") - cy.get("button[data-cy=oidc-save]").contains("Save").click({force: true}) - cy.wait("@updateAuth") - cy.get("@updateAuth").its("response.statusCode").should("eq", 200) - - cy.reload() - - cy.get("div.content").scrollTo("bottom") - - cy.get(".spectrum-Tags-item").contains("openid") - cy.get(".spectrum-Tags-item").contains("offline_access") - cy.get(".spectrum-Tags-item").contains("email") - cy.get(".spectrum-Tags-item").contains("profile") - cy.get(".spectrum-Tags-item").contains("Sample") - cy.get(".spectrum-Tags-item").contains("Another") - }) - - it("Should allow the removal of auth scopes", () => { - cy.get(".spectrum-SideNav li").contains("Auth").click() - cy.location().should(loc => { - expect(loc.pathname).to.eq("/builder/portal/manage/auth") - }) - cy.get("div.content").scrollTo("bottom") - - cy.get(".spectrum-Tags-item").contains("offline_access").parent().find(".spectrum-ClearButton").click() - cy.get(".spectrum-Tags-item").contains("profile").parent().find(".spectrum-ClearButton").click() - - cy.get(".spectrum-Tags").find(".spectrum-Tags-item").its("length").should("eq", 4) - - cy.get(".spectrum-Tags-item").contains("offline_access").should("not.exist") - cy.get(".spectrum-Tags-item").contains("profile").should("not.exist") - - cy.get("button[data-cy=oidc-save]").should("not.be.disabled"); - - cy.intercept("POST", "/api/global/configs").as("updateAuth") - cy.get("button[data-cy=oidc-save]").contains("Save").click({force: true}) - cy.wait("@updateAuth") - cy.get("@updateAuth").its("response.statusCode").should("eq", 200) - - cy.get(".spectrum-Toast-content") - .contains("Settings saved") - .should("be.visible") - - cy.reload() - - cy.get(".spectrum-Tags").find(".spectrum-Tags-item").its("length").should("eq", 4) - - cy.get(".spectrum-Tags-item").contains("offline_access").should("not.exist") - cy.get(".spectrum-Tags-item").contains("profile").should("not.exist") - }) - - it("Should allow auth scopes to be reset to the core defaults.", () => { - cy.get(".spectrum-SideNav li").contains("Auth").click() - - cy.get("div.content").scrollTo("bottom") - - cy.get("[data-cy=restore-oidc-default-scopes]").click({force: true}) - - cy.get(".spectrum-Tags").find(".spectrum-Tags-item").its("length").should("eq", 4) - - cy.get(".spectrum-Tags-item").contains("openid") - cy.get(".spectrum-Tags-item").contains("offline_access") - cy.get(".spectrum-Tags-item").contains("email") - cy.get(".spectrum-Tags-item").contains("profile") - }) - - it("Should not allow invalid characters in the auth scopes", () => { - cy.get("[data-cy=new-scope-input]").type("thisIsInvalid\\{enter}") - cy.get(".spectrum-Form-itemField .error").contains("Auth scopes cannot contain spaces, double quotes or backslashes") - cy.get(".spectrum-Tags").find(".spectrum-Tags-item").its("length").should("eq", 4) - - cy.get("[data-cy=new-scope-input]").clear() - - cy.get("[data-cy=new-scope-input]").type("alsoInvalid\"{enter}") - cy.get(".spectrum-Form-itemField .error").contains("Auth scopes cannot contain spaces, double quotes or backslashes") - cy.get(".spectrum-Tags").find(".spectrum-Tags-item").its("length").should("eq", 4) - - cy.get("[data-cy=new-scope-input]").clear() - }) - - it("Should not allow duplicate auth scopes", () => { - cy.get("[data-cy=new-scope-input]").type("offline_access{enter}") - cy.get(".spectrum-Form-itemField .error").contains("Auth scope already exists") - cy.get(".spectrum-Tags").find(".spectrum-Tags-item").its("length").should("eq", 4) - }) - - }) -}) \ No newline at end of file diff --git a/packages/builder/cypress/integration/adminAndManagement/userManagement.spec.js b/packages/builder/cypress/integration/adminAndManagement/userManagement.spec.js deleted file mode 100644 index 3d3f5d3956..0000000000 --- a/packages/builder/cypress/integration/adminAndManagement/userManagement.spec.js +++ /dev/null @@ -1,238 +0,0 @@ -import filterTests from "../../support/filterTests" -const interact = require('../../support/interact') - -filterTests(["smoke", "all"], () => { - xcontext("User Management", () => { - before(() => { - cy.login() - cy.deleteApp("Cypress Tests") - cy.createApp("Cypress Tests", false) - }) - - xit("should create a user via basic onboarding", () => { - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000}) - cy.createUser("bbuser@test.com") - cy.get(interact.SPECTRUM_TABLE).should("contain", "bbuser") - }) - - xit("should confirm App User role for a New User", () => { - cy.contains("bbuser").click() - cy.get(".spectrum-Form-itemField").eq(3).should('contain', 'App User') - - // User should not have app access - cy.get(".spectrum-Heading").contains("Apps").parent().within(() => { - cy.get(interact.LIST_ITEMS, { timeout: 500 }).should("contain", "This user has access to no apps") - }) - }) - - if (Cypress.env("TEST_ENV")) { - xit("should assign role types", () => { - // 3 apps minimum required - to assign an app to each role type - cy.request(`${Cypress.config().baseUrl}/api/applications?status=all`) - .its("body") - .then(val => { - if (val.length < 3) { - for (let i = 1; i < 3; i++) { - const uuid = () => Cypress._.random(0, 1e6) - const name = uuid() - if(i < 1){ - cy.createApp(name, false) - } else { - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000}) - cy.wait(1000) - cy.get(interact.CREATE_APP_BUTTON, { timeout: 2000 }).click({ force: true }) - cy.createAppFromScratch(name) - } - } - } - }) - // Navigate back to the user - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000}) - cy.get(interact.SPECTRUM_SIDENAV).contains("Users").click() - cy.get(interact.SPECTRUM_TABLE, { timeout: 1000 }).contains("bbuser").click() - cy.get(interact.SPECTRUM_HEADING).contains("bbuser", { timeout: 2000}) - for (let i = 0; i < 3; i++) { - cy.get(interact.SPECTRUM_TABLE, { timeout: 3000}) - .eq(1) - .find(interact.SPECTRUM_TABLE_ROW) - .eq(0) - .find(interact.SPECTRUM_TABLE_CELL) - .eq(0) - .click() - cy.get(interact.SPECTRUM_DIALOG_GRID, { timeout: 1000 }) - .contains("Choose an option") - .click() - .then(() => { - if (i == 0) { - cy.get(interact.SPECTRUM_MENU, { timeout: 2000 }).contains("Admin").click({ force: true }) - } - else if (i == 1) { - cy.get(interact.SPECTRUM_MENU, { timeout: 2000 }).contains("Power").click({ force: true }) - } - else if (i == 2) { - cy.get(interact.SPECTRUM_MENU, { timeout: 2000 }).contains("Basic").click({ force: true }) - } - cy.get(interact.SPECTRUM_BUTTON, { timeout: 2000 }) - .contains("Update role") - .click({ force: true }) - }) - cy.reload() - cy.wait(1000) - } - // Confirm roles exist within Configure roles table - cy.get(interact.SPECTRUM_TABLE, { timeout: 20000 }) - .eq(0) - .within(assginedRoles => { - expect(assginedRoles).to.contain("Admin") - expect(assginedRoles).to.contain("Power") - expect(assginedRoles).to.contain("Basic") - }) - }) - - xit("should unassign role types", () => { - // Set each app within Configure roles table to 'No Access' - cy.get(interact.SPECTRUM_TABLE) - .eq(0) - .find(interact.SPECTRUM_TABLE_ROW) - .its("length") - .then(len => { - for (let i = 0; i < len; i++) { - cy.get(interact.SPECTRUM_TABLE) - .eq(0) - .find(interact.SPECTRUM_TABLE_ROW) - .eq(0) - .find(interact.SPECTRUM_TABLE_CELL) - .eq(0) - .click() - .then(() => { - cy.get(interact.SPECTRUM_PICKER).eq(1).click({ force: true }) - cy.get(interact.SPECTRUM_POPOVER, { timeout: 500 }).contains("No Access").click() - }) - cy.get(interact.SPECTRUM_BUTTON) - .contains("Update role") - .click({ force: true }) - } - }) - // Confirm Configure roles table no longer has any apps in it - cy.get(interact.SPECTRUM_TABLE, { timeout: 1000 }).eq(0).contains("No rows found") - }) - } - - xit("should enable Developer access and verify application access", () => { - // Enable Developer access - cy.get(interact.FIELD) - .eq(4) - .within(() => { - cy.get(interact.SPECTRUM_SWITCH_INPUT).click({ force: true }) - }) - // No Access table should now be empty - cy.get(interact.CONTAINER) - .contains("No Access") - .parent() - .within(() => { - cy.get(interact.SPECTRUM_TABLE).contains("No rows found") - }) - - // Each app within Configure roles should have Admin access - cy.get(interact.SPECTRUM_TABLE) - .eq(0) - .find(interact.SPECTRUM_TABLE_ROW) - .its("length") - .then(len => { - for (let i = 0; i < len; i++) { - cy.get(interact.SPECTRUM_TABLE) - .eq(0) - .find(interact.SPECTRUM_TABLE_ROW) - .eq(i) - .contains("Admin") - cy.wait(500) - } - }) - }) - - xit("should disable Developer access and verify application access", () => { - // Disable Developer access - cy.get(interact.FIELD) - .eq(4) - .within(() => { - cy.get(".spectrum-Switch-input").click({ force: true }) - }) - // Configure roles table should now be empty - cy.get(interact.CONTAINER) - .contains("Configure roles") - .parent() - .within(() => { - cy.get(interact.SPECTRUM_TABLE).contains("No rows found") - }) - }) - - xit("Should edit user details within user details page", () => { - // Add First name - cy.get(interact.FIELD, { timeout: 1000 }).eq(1).within(() => { - cy.wait(500) - cy.get(interact.SPECTRUM_TEXTFIELD_INPUT, { timeout: 1000 }).wait(500).clear().click().type("bb") - }) - // Add Last name - cy.get(interact.FIELD, { timeout: 1000 }).eq(2).within(() => { - cy.wait(500) - cy.get(interact.SPECTRUM_TEXTFIELD_INPUT, { timeout: 1000 }).click().wait(500).clear().type("test") - }) - cy.get(interact.FIELD, { timeout: 1000 }).eq(0).click() - // Reload page - cy.reload() - - // Confirm details have been saved - cy.get(interact.FIELD, { timeout: 20000 }).eq(1).within(() => { - cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).should('have.value', "bb") - }) - cy.get(interact.FIELD, { timeout: 1000 }).eq(2).within(() => { - cy.get(interact.SPECTRUM_TEXTFIELD_INPUT, { timeout: 1000 }).should('have.value', "test") - }) - }) - - xit("should reset the users password", () => { - cy.get(".title").within(() => { - cy.get(interact.SPECTRUM_ICON).click({ force: true }) - }) - cy.get(interact.SPECTRUM_MENU).within(() => { - cy.get(interact.SPECTRUM_MENU_ITEM).contains("Force password reset").click({ force: true }) - }) - - // Reset password modal - cy.get(interact.SPECTRUM_DIALOG_GRID) - .find(interact.SPECTRUM_TEXTFIELD_INPUT).invoke('val').as('pwd') - cy.get(interact.SPECTRUM_BUTTON).contains("Reset password").click({ force: true }) - cy.get(interact.SPECTRUM_BUTTON).contains("Reset password").should('not.exist') - - // Logout, then login with new password - cy.logOut() - cy.get('@pwd').then((pwd) => { - cy.login("bbuser@test.com", pwd) - }) - - // Reset password screen - for (let i = 0; i < 2; i++) { - cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).eq(i).type("test") - } - cy.get(interact.SPECTRUM_BUTTON).contains("Reset your password").click({ force: true }) - - // Confirm user logged in afer password change - cy.login("bbuser@test.com", "test") - cy.get(".avatar > .icon").click({ force: true }) - - cy.get(".spectrum-Menu-item").contains("Update user information").click({ force: true }) - cy.get(interact.SPECTRUM_TEXTFIELD_INPUT) - .eq(0) - .invoke('val').should('eq', 'bbuser@test.com') - - // Logout and login as previous user - cy.logoutNoAppGrid() - cy.login() - }) - - xit("should delete a user", () => { - cy.deleteUser("bbuser@test.com") - cy.get(interact.SPECTRUM_TABLE, { timeout: 4000 }).should("not.have.text", "bbuser") - }) - }) -}) diff --git a/packages/builder/cypress/integration/adminAndManagement/userSettings.spec.js b/packages/builder/cypress/integration/adminAndManagement/userSettings.spec.js deleted file mode 100644 index a2b0d32d02..0000000000 --- a/packages/builder/cypress/integration/adminAndManagement/userSettings.spec.js +++ /dev/null @@ -1,109 +0,0 @@ -import filterTests from "../../support/filterTests" -const interact = require('../../support/interact') - -filterTests(["smoke", "all"], () => { - context("User Settings Menu", () => { - - before(() => { - cy.login() - }) - - it("should update user information via user settings menu", () => { - const fname = "test" - const lname = "user" - - cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.updateUserInformation(fname, lname) - - // Go to user info and confirm name update - cy.contains("Users").click() - cy.contains("test@test.com").click() - - cy.get(interact.FIELD, { timeout: 1000 }).eq(1).within(() => { - cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).should('have.value', fname) - }) - cy.get(interact.FIELD).eq(2).within(() => { - cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).should('have.value', lname) - }) - }) - - it("should allow copying of the users API key", () => { - cy.get(".user-dropdown .avatar > .icon", { timeout: 2000 }).click({ force: true }) - cy.get(interact.SPECTRUM_MENU_ITEM).contains("View API key").click({ force: true }) - cy.get(interact.SPECTRUM_DIALOG_CONTENT).within(() => { - cy.get(interact.SPECTRUM_ICON).click({force: true}) - }) - // There may be timing issues with this on the smoke build - cy.wait(500) - cy.get(".spectrum-Toast-content") - .contains("URL copied to clipboard") - .should("be.visible") - }) - - it("should allow API key regeneration", () => { - // Get initial API key value - cy.get(interact.SPECTRUM_DIALOG_CONTENT) - .find(interact.SPECTRUM_TEXTFIELD_INPUT).invoke('val').as('keyOne') - - // Click re-generate key button - cy.get("button").contains("Re-generate key").click({ force: true }) - - // Verify API key was changed - cy.get(interact.SPECTRUM_DIALOG_CONTENT).within(() => { - cy.get('@keyOne').then((keyOne) => { - cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).invoke('val').should('not.eq', keyOne) - }) - }) - cy.closeModal() - }) - - it("should update password", () => { - // Access Update password modal - cy.get(".user-dropdown .avatar > .icon", { timeout: 2000 }).click({ force: true }) - cy.get(interact.SPECTRUM_MENU_ITEM).contains("Update password").click({ force: true }) - - // Enter new password and update - cy.get(interact.SPECTRUM_DIALOG_GRID).within(() => { - for (let i = 0; i < 2; i++) { - // password set to 'newpwd' - cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).eq(i).type("newpwd") - } - cy.get("button").contains("Update password").click({ force: true }) - }) - - // Logout & in with new password - //cy.logOut() - cy.login("test@test.com", "newpwd") - }) - - it("should open and close developer mode", () => { - cy.get(".user-dropdown .avatar > .icon", { timeout: 2000 }).click({ force: true }) - - // Close developer mode & verify - cy.get(interact.SPECTRUM_MENU_ITEM).contains("Close developer mode").click({ force: true }) - cy.get(interact.SPECTRUM_SIDENAV).should('not.exist') // No config sections - cy.get(interact.CREATE_APP_BUTTON).should('not.exist') // No create app button - cy.get(".app").should('not.exist') // At least one app should be available - - // Open developer mode & verify - cy.get(".avatar > .icon").click({ force: true }) - cy.get(interact.SPECTRUM_MENU_ITEM).contains("Open developer mode").click({ force: true }) - cy.get(interact.SPECTRUM_SIDENAV).should('exist') // config sections available - cy.get(interact.CREATE_APP_BUTTON).should('exist') // create app button available - }) - - after(() => { - // Change password back to original value - cy.get(".user-dropdown .avatar > .icon", { timeout: 2000 }).click({ force: true }) - cy.get(interact.SPECTRUM_MENU_ITEM).contains("Update password").click({ force: true }) - cy.get(interact.SPECTRUM_DIALOG_GRID).within(() => { - for (let i = 0; i < 2; i++) { - cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).eq(i).type("test") - } - cy.get("button").contains("Update password").click({ force: true }) - }) - // Remove users name - cy.updateUserInformation() - }) - }) -}) diff --git a/packages/builder/cypress/integration/appOverview.spec.js b/packages/builder/cypress/integration/appOverview.spec.js deleted file mode 100644 index dafafab67a..0000000000 --- a/packages/builder/cypress/integration/appOverview.spec.js +++ /dev/null @@ -1,442 +0,0 @@ -import filterTests from "../support/filterTests" -import clientPackage from "@budibase/client/package.json" - -filterTests(["all"], () => { - context("Application Overview screen", () => { - before(() => { - cy.login() - cy.deleteAllApps() - cy.createApp("Cypress Tests") - }) - - it("Should be accessible from the applications list", () => { - cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.get(".appTable .title") - .eq(0) - .invoke("attr", "data-cy") - .then($dataCy => { - const dataCy = $dataCy - cy.get(".appTable .app-row-actions button") - .contains("Manage") - .click({ force: true }) - - cy.location().should(loc => { - expect(loc.pathname).to.eq("/builder/portal/overview/" + dataCy) - }) - }) - }) - - // Find a more suitable place for this. - it("Should allow unlocking in the app list", () => { - cy.visit(`${Cypress.config().baseUrl}/builder`) - - cy.get(".appTable .lock-status").eq(0).contains("Locked by you").click() - - cy.unlockApp({ owned: true }) - - cy.get(".appTable").should("exist") - cy.get(".lock-status").should("not.be.visible") - }) - - it("Should allow unlocking in the app overview screen", () => { - cy.visit(`${Cypress.config().baseUrl}/builder`) - - cy.get(".appTable .app-row-actions button") - .contains("Edit") - .eq(0) - .click({ force: true }) - cy.wait(1000) - cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.get(".appTable .app-row-actions button") - .contains("Manage") - .eq(0) - .click({ force: true }) - cy.get(".lock-status").eq(0).contains("Locked by you").click() - - cy.unlockApp({ owned: true }) - - cy.get(".lock-status").should("not.be.visible") - }) - - it("Should reflect the deploy state of an app that hasn't been published.", () => { - cy.visit(`${Cypress.config().baseUrl}/builder`) - - cy.get(".appTable .app-row-actions button") - .contains("Manage") - .eq(0) - .click({ force: true }) - cy.get(".header-right button.spectrum-Button[data-cy='view-app']").should( - "be.disabled" - ) - - cy.get(".spectrum-Tabs-item.is-selected").contains("Overview") - cy.get(".overview-tab").should("be.visible") - - cy.get(".overview-tab [data-cy='app-status']").within(() => { - cy.get(".status-display").contains("Unpublished") - cy.get(".status-display .icon svg[aria-label='GlobeStrike']").should( - "exist" - ) - cy.get(".status-text").contains("-") - }) - }) - - it("Should reflect the app deployment state", () => { - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 }) - cy.get(".appTable .app-row-actions button") - .contains("Edit") - .eq(0) - .click({ force: true }) - - cy.wait(500) - cy.get(".toprightnav button.spectrum-Button", { timeout: 2000 }) - .contains("Publish") - .click({ force: true }) - cy.get(".spectrum-Modal [data-cy='deploy-app-modal']") - .should("be.visible") - .within(() => { - cy.get(".spectrum-Button").contains("Publish").click({ force: true }) - cy.wait(1000) - }) - - cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.get(".appTable .app-row-actions button") - .contains("Manage") - .eq(0) - .click({ force: true }) - cy.get(".header-right button.spectrum-Button[data-cy='view-app']").should( - "not.be.disabled" - ) - - cy.get(".overview-tab [data-cy='app-status']").within(() => { - cy.get(".status-display").contains("Published") - cy.get(".status-display .icon svg[aria-label='GlobeCheck']").should( - "exist" - ) - cy.get(".status-text").contains("Last published a few seconds ago") - }) - }) - - it("Should reflect an application that has been unpublished", () => { - cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.get(".appTable .app-row-actions button") - .contains("Edit") - .eq(0) - .click({ force: true }) - - cy.get(".deployment-top-nav svg[aria-label='Globe']").click({ - force: true, - }) - - cy.get("[data-cy='publish-popover-menu']").should("be.visible") - cy.get( - "[data-cy='publish-popover-menu'] [data-cy='publish-popover-action']" - ).click({ force: true }) - - cy.get("[data-cy='unpublish-modal']") - .should("be.visible") - .within(() => { - cy.get(".confirm-wrap button").click({ force: true }) - }) - - cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.wait(1000) - cy.get(".appTable .app-row-actions button", { timeout: 10000 }) - .contains("Manage") - .eq(0) - .click({ force: true }) - cy.get(".overview-tab [data-cy='app-status']").within(() => { - cy.get(".status-display").contains("Unpublished") - cy.get(".status-display .icon svg[aria-label='GlobeStrike']").should( - "exist" - ) - cy.get(".status-text").contains("Last published a few seconds ago") - }) - }) - - it("Should allow the editing of the application icon and colour", () => { - cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.get(".appTable .app-row-actions button") - .contains("Manage") - .eq(0) - .click({ force: true }) - cy.get(".edit-hover", { timeout: 1000 }).eq(0).click({ force: true }) - // Select random icon - cy.wait(400) - cy.get(".grid").within(() => { - cy.get(".icon-item") - .eq(Math.floor(Math.random() * 23) + 1) - .click() - }) - // Select random colour - cy.get(".fill").click() - cy.get(".colors").within(() => { - cy.get(".color") - .eq(Math.floor(Math.random() * 33) + 1) - .click() - }) - cy.intercept("**/applications/**").as("iconChange") - cy.get(".spectrum-Button").contains("Save").click({ force: true }) - cy.wait("@iconChange") - cy.get("@iconChange").its("response.statusCode").should("eq", 200) - // Confirm icon has changed from default - // Confirm colour has been applied - cy.get(".spectrum-ActionButton-label").contains("Back").click({ force: true }) - cy.get(".appTable", { timeout: 2000 }).within(() => { - cy.get("[aria-label]") - .eq(0) - .children() - .should("have.attr", "xlink:href") - .and("not.contain", "#spectrum-icon-18-Apps") - cy.get(".title") - .children() - .children() - .should("have.attr", "style") - .and("contains", "color") - }) - }) - - it("Should reflect the last time the application was edited", () => { - cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.get(".appTable .app-row-actions button") - .contains("Manage") - .eq(0) - .click({ force: true }) - cy.get(".header-right button").contains("Edit").click({ force: true }) - - cy.navigateToFrontend() - - cy.searchAndAddComponent("Headline").then(componentId => { - cy.getComponent(componentId).should("exist") - }) - - cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.get(".appTable .app-row-actions button") - .contains("Manage") - .eq(0) - .click({ force: true }) - cy.get(".overview-tab [data-cy='edited-by']").within(() => { - cy.get(".editor-name").contains("You") - cy.get(".last-edit-text").contains("Last edited a few seconds ago") - }) - }) - - it("Should reflect application version is up-to-date", () => { - cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.get(".appTable .app-row-actions button") - .contains("Manage") - .eq(0) - .click({ force: true }) - cy.get(".overview-tab [data-cy='app-version']").within(() => { - cy.get(".version-status").contains("You're running the latest!") - }) - }) - - it("Should navigate to the settings tab when clicking the App Version card header", () => { - cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.get(".appTable .app-row-actions button") - .contains("Manage") - .eq(0) - .click({ force: true }) - cy.get(".spectrum-Tabs-item.is-selected").contains("Overview") - cy.get(".overview-tab").should("be.visible") - - cy.get(".overview-tab [data-cy='app-version'] .dash-card-header").click({ - force: true, - }) - - cy.get(".spectrum-Tabs-item.is-selected").contains("Settings") - cy.get(".settings-tab").should("be.visible") - cy.get(".overview-tab").should("not.exist") - }) - - it("Should allow the upgrading of an application, if available.", () => { - cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.get(".appTable .app-row-actions button") - .contains("Manage") - .eq(0) - .click({ force: true }) - cy.wait(500) - - cy.location().then(loc => { - const params = loc.pathname.split("/") - const appId = params[params.length - 1] - cy.log(appId) - //Downgrade the app for the test - cy.alterAppVersion(appId, "0.0.1-alpha.0").then(() => { - cy.reload() - cy.log("Current deployment version: " + clientPackage.version) - - cy.get(".version-status a", { timeout: 5000 }).contains("Update").click() - cy.get(".spectrum-Tabs-item.is-selected").contains("Settings") - - cy.get(".version-section .page-action button") - .contains("Update") - .click({ force: true }) - - cy.intercept("POST", "**/applications/**/client/update").as( - "updateVersion" - ) - cy.get(".spectrum-Modal.is-open button") - .contains("Update") - .click({ force: true }) - - cy.wait("@updateVersion") - .its("response.statusCode") - .should("eq", 200) - .then(() => { - cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.get(".appTable .app-row-actions button") - .contains("Manage") - .eq(0) - .click({ force: true }) - cy.get(".spectrum-Tabs-item") - .contains("Overview") - .click({ force: true }) - cy.get(".overview-tab [data-cy='app-version']").within(() => { - cy.get(".spectrum-Heading").contains(clientPackage.version) - cy.get(".version-status").contains("You're running the latest!") - }) - }) - }) - }) - }) - - it("Should allow editing of the app details.", () => { - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 }) - cy.get(".appTable .app-row-actions button") - .contains("Manage") - .eq(0) - .click({ force: true }) - cy.get(".spectrum-Tabs-item").contains("Settings").click() - cy.get(".spectrum-Tabs-item.is-selected").contains("Settings") - cy.get(".settings-tab").should("be.visible") - - cy.get(".details-section .page-action button") - .contains("Edit") - .click({ force: true }) - cy.updateAppName("sample name") - - //publish and check its disabled - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 }) - cy.wait(500) - cy.get(".appTable .app-row-actions button") - .contains("Edit") - .eq(0) - .click({ force: true }) - - cy.get(".toprightnav button.spectrum-Button") - .contains("Publish") - .click({ force: true }) - cy.get(".spectrum-Modal [data-cy='deploy-app-modal']") - .should("be.visible") - .within(() => { - cy.get(".spectrum-Button").contains("Publish").click({ force: true }) - cy.wait(1000) - }) - - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 10000 }) - cy.get(".appTable .app-row-actions button", { timeout: 5000 }) - .contains("Manage") - .eq(0) - .click({ force: true }) - cy.get(".spectrum-Tabs-item").contains("Settings").click() - cy.get(".spectrum-Tabs-item.is-selected").contains("Settings") - - cy.get(".details-section .page-action .spectrum-Button").scrollIntoView() - cy.get(".details-section .page-action .spectrum-Button", { timeout: 1000 }).should( - "be.disabled" - ) - }) - - xit("Should allow copying of the published application Id", () => { - cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.get(".appTable .app-row-actions") - .eq(0) - .within(() => { - cy.get(".spectrum-Button").contains("Edit").click({ force: true }) - }) - - cy.publishApp("sample-name") - - cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.get(".appTable .app-row-actions button") - .contains("Manage") - .eq(0) - .click({ force: true }) - cy.get(".app-overview-actions-icon > .icon").click({ force: true }) - - cy.get("[data-cy='app-overview-menu-popover']") - .eq(0) - .within(() => { - cy.get(".spectrum-Menu-item") - .contains("Copy App ID") - .click({ force: true }) - }) - - cy.get(".spectrum-Toast-content") - .contains("App ID copied to clipboard.") - .should("be.visible") - }) - - it("Should allow unpublishing of the application via the Unpublish link", () => { - cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.get(".appTable .app-row-actions button") - .contains("Manage") - .eq(0) - .click({ force: true }) - - cy.get(`[data-cy="app-status"]`).within(() => { - cy.contains("Unpublish").click({ force: true }) - }) - - cy.get("[data-cy='unpublish-modal']") - .should("be.visible") - .within(() => { - cy.get(".confirm-wrap button").click({ force: true }) - }) - - cy.get(".overview-tab [data-cy='app-status']").within(() => { - cy.get(".status-display").contains("Unpublished") - cy.get(".status-display .icon svg[aria-label='GlobeStrike']") - .should("exist") - }) - }) - - it("Should allow deleting of the application", () => { - cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.get(".appTable .app-row-actions button") - .contains("Manage") - .eq(0) - .click({ force: true }) - cy.get(".app-overview-actions-icon > .icon").click({ force: true }) - - cy.get("[data-cy='app-overview-menu-popover']") - .eq(0) - .within(() => { - cy.get(".spectrum-Menu-item") - .contains("Delete") - .click({ force: true }) - cy.wait(500) - }) - - //The test application was renamed earlier in the spec - cy.get(".spectrum-Dialog-grid").within(() => { - cy.get("input").type("sample name") - cy.get(".spectrum-Button--warning").click() - }) - - cy.location().should(loc => { - expect(loc.pathname).to.eq("/builder/portal/apps") - }) - - cy.get(".appTable").should("not.exist") - - cy.get(".welcome .container h1").contains("Let's create your first app!") - }) - - after(() => { - cy.deleteAllApps() - }) - }) -}) diff --git a/packages/builder/cypress/integration/appPublishWorkflow.spec.js b/packages/builder/cypress/integration/appPublishWorkflow.spec.js deleted file mode 100644 index ab799f40fe..0000000000 --- a/packages/builder/cypress/integration/appPublishWorkflow.spec.js +++ /dev/null @@ -1,107 +0,0 @@ -import filterTests from "../support/filterTests" -import { APP_TABLE_APP_NAME, DEPLOY_SUCCESS_MODAL } from "../support/interact"; -const interact = require('../support/interact') - -filterTests(['all'], () => { - context("Publish Application Workflow", () => { - before(() => { - cy.login() - cy.deleteAllApps() - cy.createApp("Cypress Tests", false) - }) - - it("Should reflect the unpublished status correctly", () => { - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 }) - - cy.get(interact.APP_TABLE_STATUS, { timeout: 3000 }).eq(0) - .within(() => { - cy.contains("Unpublished") - cy.get(interact.GLOBESTRIKE).should("exist") - }) - - cy.get(interact.APP_TABLE_ROW_ACTION).eq(0) - .within(() => { - cy.get(interact.SPECTRUM_BUTTON_TEMPLATE).contains("Edit").click({ force: true }) - }) - - cy.get(interact.DEPLOYMENT_TOP_NAV_GLOBESTRIKE).should("exist") - cy.get(interact.DEPLOYMENT_TOP_GLOBE).should("not.exist") - }) - - it("Should publish an application and correctly reflect that", () => { - //Assuming the previous test was run and the unpublished app is open in edit mode. - cy.get(interact.TOPRIGHTNAV_BUTTON_SPECTRUM).contains("Publish").click({ force : true }) - - cy.get(interact.DEPLOY_APP_MODAL).should("be.visible") - .within(() => { - cy.get(interact.SPECTRUM_BUTTON).contains("Publish").click({ force : true }) - }); - - //Verify that the app url is presented correctly to the user - cy.get(interact.DEPLOY_SUCCESS_MODAL, { timeout: 1000 }) - .should("be.visible") - .within(() => { - let appUrl = Cypress.config().baseUrl + '/app/cypress-tests' - cy.get(interact.DEPLOY_APP_URL_INPUT).should('have.value', appUrl) - cy.get(interact.SPECTRUM_BUTTON).contains("Done").click({ force: true }) - }) - - cy.visit(`${Cypress.config().baseUrl}/builder`) - - cy.get(interact.APP_TABLE_STATUS, { timeout: 3000 }).eq(0) - .within(() => { - cy.contains("Published") - cy.get(interact.GLOBE).should("exist") - }) - - cy.get(interact.APP_TABLE_ROW_ACTION).eq(0) - .within(() => { - cy.get(interact.SPECTRUM_BUTTON).contains("Manage") - cy.get(interact.SPECTRUM_BUTTON).contains("Edit").click({ force: true }) - }) - - cy.get(interact.DEPLOYMENT_TOP_GLOBE).should("exist").click({ force: true }) - - cy.get(interact.PUBLISH_POPOVER_MENU).should("be.visible") - .within(() => { - cy.get(interact.PUBLISH_POPOVER_ACTION).should("exist") - cy.get("button").contains("View app").should("exist") - cy.get(interact.PUBLISH_POPOVER_MESSAGE).should("have.text", "Last published a few seconds ago") - }) - }) - - it("Should unpublish an application using the link and reflect the status change", () => { - //Assuming the previous test app exists and is published - - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 }) - - cy.get(interact.APP_TABLE_STATUS).eq(0) - .within(() => { - cy.contains("Published") - cy.get("svg[aria-label='Globe']").should("exist") - }) - - cy.get(interact.APP_TABLE).eq(0) - .within(() => { - cy.get(interact.APP_TABLE_APP_NAME).click({ force: true }) - }) - - cy.get(interact.DEPLOYMENT_TOP_GLOBE).should("exist").click({ force: true }) - - cy.get("[data-cy='publish-popover-menu']") - .within(() => { - cy.get(interact.PUBLISH_POPOVER_ACTION).click({ force: true }) - }) - - cy.get(interact.UNPUBLISH_MODAL).should("be.visible") - .within(() => { - cy.get(interact.CONFIRM_WRAP_BUTTON).click({ force: true } - )}) - - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 6000 }) - cy.wait(500) - cy.get(interact.APP_TABLE_STATUS, { timeout: 10000 }).eq(0).contains("Unpublished") - - }) - }) -}) diff --git a/packages/builder/cypress/integration/autoScreensUI.spec.js b/packages/builder/cypress/integration/autoScreensUI.spec.js deleted file mode 100644 index 581e5c431b..0000000000 --- a/packages/builder/cypress/integration/autoScreensUI.spec.js +++ /dev/null @@ -1,101 +0,0 @@ -import filterTests from "../support/filterTests" -const interact = require('../support/interact') - -filterTests(['smoke', 'all'], () => { - xcontext("Auto Screens UI", () => { - before(() => { - cy.login() - cy.deleteAllApps() - }) - - it("should disable the autogenerated screen options if no sources are available", () => { - cy.createApp("First Test App", false) - cy.closeModal(); - - cy.navigateToAutogeneratedModal() - cy.get(interact.CONFIRM_WRAP_SPE_BUTTON).should('be.disabled') - - cy.deleteAllApps() - }); - - it("should not display incompatible sources", () => { - cy.createApp("Test App") - - cy.selectExternalDatasource("REST") - cy.selectExternalDatasource("S3") - cy.get(interact.SPECTRUM_MODAL).within(() => { - cy.get(interact.SPECTRUM_BUTTON).contains("Save and continue to query").click({ force : true }) - }) - - cy.navigateToAutogeneratedModal() - - cy.get(interact.DATA_SOURCE_ENTRY).should('have.length', 1) - cy.get(interact.DATA_SOURCE_ENTRY) - - cy.deleteAllApps() - }); - - it("should generate internal table screens", () => { - cy.createTestApp() - // Create Autogenerated screens from the internal table - cy.createDatasourceScreen(["Cypress Tests"]) - // Confirm screens have been auto generated - cy.get(interact.BODY).should('contain', "cypress-tests") - .and('contain', 'cypress-tests/:id') - .and('contain', 'cypress-tests/new/row') - }) - - it("should generate multiple internal table screens at once", () => { - const initialTable = "Cypress Tests" - const secondTable = "Table Two" - // Create a second internal table - cy.createTable(secondTable) - // Create Autogenerated screens from the internal tables - cy.createDatasourceScreen([initialTable, secondTable]) - // Confirm screens have been auto generated - // Previously generated tables are suffixed with numbers - as expected - cy.wait(1000) - cy.get(interact.BODY).should('contain', 'cypress-tests-2') - .and('contain', 'cypress-tests-2/:id') - .and('contain', 'cypress-tests-2/new/row') - .and('contain', 'table-two') - .and('contain', 'table-two/:id') - .and('contain', 'table-two/new/row') - }) - - it("should generate multiple internal table screens with the same screen access level", () => { - //The tables created in the previous step still exist - cy.createTable("Table Three") - cy.createTable("Table Four") - cy.createDatasourceScreen(["Table Three", "Table Four"], "Admin") - - // Filter screens to Admin - cy.filterScreensAccessLevel('Admin') - - cy.get(interact.BODY).should('contain', 'table-three') - .and('contain', 'table-three/:id') - .and('contain', 'table-three/new/row') - .and('contain', 'table-four') - .and('contain', 'table-four/:id') - .and('contain', 'table-four/new/row') - .and('not.contain', 'table-two') - .and('not.contain', 'cypress-tests') - }) - - if (Cypress.env("TEST_ENV")) { - it("should generate datasource screens", () => { - // Using MySQL datasource for testing this - const datasource = "MySQL" - // Select & configure MySQL datasource - cy.selectExternalDatasource(datasource) - cy.addDatasourceConfig(datasource) - // Create Autogenerated screens from a MySQL table - MySQL contains books table - cy.createDatasourceScreen(["books"]) - - cy.get(interact.BODY).should('contain', 'books') - .and('contain', 'books/:id') - .and('contain', 'books/new/row') - }) - } - }) -}) diff --git a/packages/builder/cypress/integration/createApp.spec.js b/packages/builder/cypress/integration/createApp.spec.js deleted file mode 100644 index d37b0806c4..0000000000 --- a/packages/builder/cypress/integration/createApp.spec.js +++ /dev/null @@ -1,221 +0,0 @@ -import filterTests from '../support/filterTests' -const interact = require('../support/interact') - -filterTests(['smoke', 'all'], () => { - context("Create an Application", () => { - - before(() => { - cy.login() - cy.deleteAllApps() - }) - - if (!(Cypress.env("TEST_ENV"))) { - it.skip("should show the new user UI/UX", () => { - cy.visit(`${Cypress.config().baseUrl}/builder/portal/apps/create`, { timeout: 5000 }) //added /portal/apps/create - cy.wait(1000) - cy.get(interact.CREATE_APP_BUTTON, { timeout: 10000 }).contains('Start from scratch').should("exist") - - cy.get(interact.TEMPLATE_CATEGORY_FILTER).should("exist") - cy.get(interact.TEMPLATE_CATEGORY).should("exist") - - cy.get(interact.APP_TABLE).should("not.exist") - }) - } - - it("should provide filterable templates", () => { - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 }) - cy.wait(500) - - cy.request(`${Cypress.config().baseUrl}/api/applications?status=all`) - .its("body") - .then(val => { - if (val.length > 0) { - cy.get(interact.SPECTRUM_BUTTON).contains("Templates").click({force: true}) - } - }) - - cy.get(interact.TEMPLATE_CATEGORY_FILTER).should("exist") - cy.get(interact.TEMPLATE_CATEGORY).should("exist") - - cy.get(interact.TEMPLATE_CATEGORY_ACTIONGROUP).its('length').should('be.gt', 1) - cy.get(interact.TEMPLATE_CATEGORY_FILTER_ACTIONBUTTON).its('length').should('be.gt', 2) - - cy.get(interact.TEMPLATE_CATEGORY_FILTER_ACTIONBUTTON).eq(1).click() - cy.get(interact.TEMPLATE_CATEGORY_ACTIONGROUP).should('have.length', 1) - - cy.get(interact.TEMPLATE_CATEGORY_FILTER_ACTIONBUTTON).eq(0).click() - cy.get(interact.TEMPLATE_CATEGORY_ACTIONGROUP).its('length').should('be.gt', 1) - }) - - it("should enforce a valid url before submission", () => { - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 10000 }) - - // Start create app process. If apps already exist, click second button - cy.wait(1000) - cy.get(interact.CREATE_APP_BUTTON, { timeout: 3000 }).click({ force: true }) - - const appName = "Cypress Tests" - cy.get(interact.SPECTRUM_MODAL).within(() => { - - cy.get(interact.APP_NAME_INPUT).eq(0).should('have.focus') - - //Auto fill - cy.get(interact.APP_NAME_INPUT).eq(0).clear() - cy.get(interact.APP_NAME_INPUT).eq(0).type(appName).should("have.value", appName).blur() - cy.get(interact.APP_NAME_INPUT).eq(1).should("have.value", "/cypress-tests") - cy.get(interact.SPECTRUM_BUTTON_GROUP).contains("Create app").should('not.be.disabled') - - //Empty the app url - disabled create - cy.get(interact.APP_NAME_INPUT).eq(1).clear().blur() - cy.get(interact.SPECTRUM_BUTTON_GROUP).contains("Create app").should('be.disabled') - - //Invalid url - cy.get(interact.APP_NAME_INPUT).eq(1).type("/new app-url").blur() - cy.get(interact.SPECTRUM_BUTTON_GROUP).contains("Create app").should('be.disabled') - - //Specifically alter the url - cy.get(interact.APP_NAME_INPUT).eq(1).clear() - cy.get(interact.APP_NAME_INPUT).eq(1).type("another-app-name").blur() - cy.get(interact.APP_NAME_INPUT).eq(1).should("have.value", "/another-app-name") - cy.get(interact.APP_NAME_INPUT).eq(0).should("have.value", appName) - cy.get(interact.SPECTRUM_BUTTON_GROUP).contains("Create app").should('not.be.disabled') - - }) - }) - - it.skip("should create the first application from scratch", () => { - const appName = "Cypress Tests" - cy.createApp(appName, false) - - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 }) - - cy.applicationInAppTable(appName) - cy.deleteApp(appName) - }) - - it.skip("should create the first application from scratch with a default name", () => { - cy.updateUserInformation("", "") - cy.createApp("", false) - cy.applicationInAppTable("My app") - cy.deleteApp("My app") - }) - - it("should create the first application from scratch, using the users first name as the default app name", () => { - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 }) - - cy.updateUserInformation("Ted", "Userman") - - cy.createApp("", false) - cy.applicationInAppTable("Teds app") - cy.deleteApp("Teds app") - - // Accomodate names that end in 'S' - cy.updateUserInformation("Chris", "Userman") - - cy.createApp("", false) - cy.applicationInAppTable("Chris app") - cy.deleteApp("Chris app") - - cy.updateUserInformation("", "") - }) - - it("should create an application from an export", () => { - const exportedApp = 'cypress/fixtures/exported-app.txt' - - cy.importApp(exportedApp, "") - - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 2000 }) - - cy.applicationInAppTable("My app") - - cy.get(".appTable .name").eq(0).click() - - cy.deleteApp("My app") - }) - - it("should create an application from an export, using the users first name as the default app name", () => { - const exportedApp = 'cypress/fixtures/exported-app.txt' - - cy.updateUserInformation("Ted", "Userman") - - cy.importApp(exportedApp, "") - - cy.visit(`${Cypress.config().baseUrl}/builder`) - - cy.applicationInAppTable("Teds app") - - cy.get(".appTable .name").eq(0).click() - - cy.deleteApp("Teds app") - - cy.updateUserInformation("", "") - }) - - it("should generate the first application from a template", () => { - cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.wait(500) - - // Navigate to Create new app section if apps already exist - cy.request(`${Cypress.config().baseUrl}/api/applications?status=all`) - .its("body") - .then(val => { - if (val.length > 0) { - cy.get(interact.CREATE_APP_BUTTON).click({ force: true }) - } - }) - - cy.get(interact.TEMPLATE_CATEGORY_FILTER).should("exist") - cy.get(interact.TEMPLATE_CATEGORY).should("exist") - - // Select template - cy.get(interact.TEMPLATE_CATEGORY_ACTIONGROUP).eq(0).within(() => { - const card = cy.get('.template-card').eq(0).should("exist"); - const cardOverlay = card.get('.template-thumbnail-action-overlay').should("exist") - cardOverlay.invoke("show") - cardOverlay.get("button").contains("Use template").should("exist").click({force: true}) - }) - - // CMD Create app from theme card - cy.get(".spectrum-Modal").should('be.visible') - - const templateName = cy.get(".spectrum-Modal .template-thumbnail-text") - templateName.invoke('text') - .then(templateNameText => { - const templateNameParsed = "/"+templateNameText.toLowerCase().replace(/\s+/g, "-") - cy.get(interact.SPECTRUM_MODAL_INPUT).eq(0).should("have.value", templateNameText) - cy.get(interact.SPECTRUM_MODAL_INPUT).eq(1).should("have.value", templateNameParsed) - - cy.get(".spectrum-Modal .spectrum-ButtonGroup").contains("Create app").click() - cy.wait(5000) - - cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.wait(2000) - - cy.applicationInAppTable(templateNameText) - cy.deleteApp(templateNameText) - }); - - }) - - it("should display a second application and app filtering", () => { - // Create first app - const appName = "Cypress Tests" - cy.createApp(appName) - - cy.visit(`${Cypress.config().baseUrl}/builder`) - - // Create second app - const secondAppName = "Second App Demo" - cy.createApp(secondAppName) - - cy.visit(`${Cypress.config().baseUrl}/builder`) - - //Both applications should exist and be searchable - cy.searchForApplication(appName) - cy.searchForApplication(secondAppName) - - cy.deleteApp(secondAppName) - }) - - }) -}) diff --git a/packages/builder/cypress/integration/createAutomation.spec.js b/packages/builder/cypress/integration/createAutomation.spec.js deleted file mode 100644 index 8c16f4bd22..0000000000 --- a/packages/builder/cypress/integration/createAutomation.spec.js +++ /dev/null @@ -1,64 +0,0 @@ -import filterTests from "../support/filterTests" -const interact = require('../support/interact') - -filterTests(['smoke', 'all'], () => { - context("Create a automation", () => { - before(() => { - cy.login() - cy.createTestApp() - }) - - it("should create a automation", () => { - cy.createTestTableWithData() - cy.wait(2000) - cy.contains("Automate").click() - cy.get(interact.SPECTRUM_BUTTON_TEMPLATE).contains("Add automation").click({ force: true }) - cy.get(interact.MODAL_INNER_WRAPPER).within(() => { - cy.get("input").type("Add Row") - cy.contains("Row Created").click({ force: true }) - cy.get(interact.SPECTRUM_BUTTON_CTA, { timeout: 500 }).click() - }) - - // Setup trigger - cy.get(interact.SPECTRUM_PICKER_LABEL).click() - cy.wait(500) - cy.contains("dog").click() - // Create action - cy.get('[aria-label="AddCircle"]', { timeout: 2000 }).click() - cy.get(interact.MODAL_INNER_WRAPPER).within(() => { - cy.wait(1000) - cy.contains("Create Row").trigger('mouseover').click().click() - cy.get(interact.SPECTRUM_BUTTON_CTA).click() - }) - cy.get(interact.SPECTRUM_PICKER_LABEL).eq(1).click() - cy.contains("dog").click() - cy.get(interact.SPECTRUM_TEXTFIELD_INPUT) - .first() - .type("{{ trigger.row.name }}", { parseSpecialCharSequences: false }) - cy.get(interact.SPECTRUM_TEXTFIELD_INPUT) - .eq(1) - .type("11") - cy.contains("Finish and test automation").click() - - cy.get(interact.MODAL_INNER_WRAPPER).within(() => { - cy.get(interact.SPECTRUM_PICKER_LABEL, { timeout: 1000 }).click() - cy.contains("dog").click() - cy.get(interact.SPECTRUM_TEXTFIELD_INPUT, { timeout: 1000 }) - .first() - .type("automationGoodboy") - cy.get(interact.SPECTRUM_TEXTFIELD_INPUT) - .eq(1) - .type("11") - cy.get(interact.SPECTRUM_TEXTFIELD_INPUT) - .eq(2) - .type("123456") - cy.get(interact.SPECTRUM_TEXTFIELD_INPUT) - .eq(3) - .type("123456") - cy.contains("Test").click() - }) - cy.contains("Data").click() - cy.contains("automationGoodboy") - }) - }) -}) diff --git a/packages/builder/cypress/integration/createBinding.spec.js b/packages/builder/cypress/integration/createBinding.spec.js deleted file mode 100644 index 0722d29f1d..0000000000 --- a/packages/builder/cypress/integration/createBinding.spec.js +++ /dev/null @@ -1,66 +0,0 @@ -import filterTests from "../support/filterTests" - -filterTests(['smoke', 'all'], () => { - context("Create Bindings", () => { - before(() => { - cy.login() - cy.createTestApp() - cy.navigateToFrontend() - }) - - it("should add a current user binding", () => { - cy.searchAndAddComponent("Paragraph").then(componentId => { - addSettingBinding("text", ["Current User", "_id"], "Current User._id") - }) - cy.deleteComponentByName("New Paragraph") - }) - - it("should handle an invalid binding", () => { - cy.searchAndAddComponent("Paragraph").then(componentId => { - // Cypress needs to escape curly brackets - cy.get("[data-cy=setting-text] input") - .type("{{}{{}{{} Current User._id {}}{}}") - .blur() - cy.getComponent(componentId).should("have.text", "{{{ [user].[_id] }}") - cy.deleteComponentByName("New Paragraph") - }) - }) - - xit("should add a URL param binding", () => { - const paramName = "foo" - cy.createScreen(`/test/:${paramName}`) - cy.searchAndAddComponent("Paragraph").then(componentId => { - addSettingBinding("text", ["URL", paramName], `URL.${paramName}`) - // The builder preview pages don't have a real URL, so all we can do - // is check that we were able to bind to the property, and that the - // component exists on the page - cy.getComponent(componentId).should("have.text", "New Paragraph") - }) - }) - - it("should add a binding with a handlebars helper", () => { - cy.searchAndAddComponent("Paragraph").then(componentId => { - // Cypress needs to escape curly brackets - cy.get("[data-cy=setting-text] input") - .type("{{}{{} add 1 2 {}}{}}") - .blur() - cy.getComponent(componentId).should("have.text", "3") - }) - }) - }) - - const addSettingBinding = (setting, bindingCategories, bindingText, clickOption = true) => { - cy.get(`[data-cy="setting-${setting}"] [data-cy=text-binding-button]`).click() - cy.get(".category-list li").contains(bindingCategories[0]) - cy.get(".drawer").within(() => { - if (clickOption) { - cy.get(".category-list li").contains(bindingCategories[0]).click() - cy.get("li.binding").contains(bindingCategories[1]).click() - cy.get("textarea").should("have.value", `{{ ${bindingText} }}`) - } else { - cy.get("textarea").type(bindingText) - } - cy.contains("Save").click() - }) - } -}) diff --git a/packages/builder/cypress/integration/createComponents.spec.js b/packages/builder/cypress/integration/createComponents.spec.js deleted file mode 100644 index 7f29466258..0000000000 --- a/packages/builder/cypress/integration/createComponents.spec.js +++ /dev/null @@ -1,275 +0,0 @@ -import filterTests from "../support/filterTests" -const interact = require("../support/interact") - -filterTests(["all"], () => { - xcontext("Create Components", () => { - let headlineId - - before(() => { - cy.login() - cy.createTestApp() - cy.createTable("dog") - cy.addColumn("dog", "name", "Text") - cy.addColumn("dog", "age", "Number") - cy.addColumn("dog", "breed", "Options") - - cy.navigateToFrontend() - cy.wait(1000) //allow the iframe some wiggle room - }) - - //Use the tree to delete a selected component - const deleteSelectedComponent = () => { - cy.get( - ".nav-item.selected .actions > div > .icon" - ).click({ - force: true, - }) - cy.get(".spectrum-Popover.is-open li").contains("Delete").click() - cy.get(".spectrum-Modal button").contains("Delete Component").click({ - force: true, - }) - } - - it("should add a container", () => { - cy.searchAndAddComponent("Container").then(componentId => { - cy.getComponent(componentId).should("exist") - }) - }) - - it("should add a headline", () => { - cy.searchAndAddComponent("Headline").then(componentId => { - headlineId = componentId - cy.getComponent(headlineId).should("exist") - }) - }) - - it("should change the text of the headline", () => { - const text = "Lorem ipsum dolor sit amet." - cy.get("[data-cy=setting-text] input").type(text).blur() - cy.getComponent(headlineId).should("have.text", text) - }) - - it("should change the size of the headline", () => { - cy.get("[data-cy=setting-size]").scrollIntoView().click() - cy.get("[data-cy=setting-size]").within(() => { - cy.get(".spectrum-Form-item li.spectrum-Menu-item") - .contains("3XL") - .click() - }) - - cy.getComponent(headlineId).within(() => { - cy.get(".spectrum-Heading").should("have.css", "font-size", "60px") - }) - }) - - it("should create a form and reset to match schema", () => { - cy.searchAndAddComponent("Form").then(() => { - cy.get("[data-cy=setting-dataSource]").contains("Custom").click() - cy.get(interact.DROPDOWN).contains("dog").click() - cy.wait(500) - cy.searchAndAddComponent("Field Group").then(fieldGroupId => { - cy.contains("Update form fields").click() - cy.get(".spectrum-Modal") - .get(".confirm-wrap .spectrum-Button") - .click() - cy.wait(500) - cy.getComponent(fieldGroupId).within(() => { - cy.contains("name").should("exist") - cy.contains("age").should("exist") - cy.contains("breed").should("exist") - // cy.contains("image").should("exist") - }) - cy.getComponent(fieldGroupId).find("input").should("have.length", 2) - cy.getComponent(fieldGroupId) - .find(interact.SPECTRUM_PICKER) - .should("have.length", 1) - }) - }) - }) - - it("deletes a component", () => { - cy.searchAndAddComponent("Paragraph").then(componentId => { - cy.get("[data-cy=setting-_instanceName] input").type(componentId).blur() - cy.get( - ".nav-item.selected .actions > div > .icon" - ).click({ - force: true, - }) - cy.get(".spectrum-Popover.is-open li").contains("Delete").click() - cy.get(".spectrum-Modal button").contains("Delete Component").click({ - force: true, - }) - cy.getComponent(componentId).should("not.exist") - }) - }) - - it("should clear the iframe place holder when a form field has been set", () => { - cy.searchAndAddComponent("Form").then(formId => { - //For deletion - cy.get("[data-cy=setting-_instanceName] input") - .clear() - .type(formId) - .blur() - cy.get("[data-cy=setting-dataSource]").contains("Custom").click() - cy.get(".dropdown").contains("dog").click() - - const fieldTypeToColumnName = { - "Text Field": "name", - "Number Field": "age", - "Options Picker": "breed", - } - - const componentTypeLabels = Object.keys(fieldTypeToColumnName) - - const testFieldFocusOnCreate = componentLabel => { - cy.log("Adding: " + componentLabel) - return cy.searchAndAddComponent(componentLabel).then(componentId => { - cy.get("[data-cy=setting-field] button.spectrum-Picker").click() - - //Click the first appropriate field. They are filtered by type - cy.get( - "[data-cy=setting-field] .spectrum-Popover.is-open li.spectrum-Menu-item" - ) - .contains(fieldTypeToColumnName[componentLabel]) - .click() - cy.wait(500) - cy.getComponent(componentId) - .find(".component-placeholder") - .should("not.exist") - }) - } - - cy.wait(500) - cy.wrap(componentTypeLabels) - .each(label => { - return testFieldFocusOnCreate(label) - }) - .then(() => { - cy.get(".nav-item") - .contains(formId) - .click({ force: true }) - deleteSelectedComponent() - }) - }) - }) - - it("should populate the provider for charts with a data provider in its path", () => { - cy.searchAndAddComponent("Data Provider").then(providerId => { - //For deletion - cy.get("[data-cy=setting-_instanceName] input") - .clear() - .type(providerId) - .blur() - cy.get("[data-cy=setting-dataSource]") - .contains("Choose an option") - .click() - cy.get(`[data-cy=dataSource-popover-${providerId}] ul li`) - .contains("dog") - .click() - - const chartTypeLabels = [ - "Bar Chart", - "Line Chart", - "Area Chart", - "Pie Chart", - "Donut Chart", - "Candlestick Chart", - ] - - const testFocusOnCreate = chartLabel => { - cy.log("Adding: " + chartLabel) - cy.searchAndAddComponent(chartLabel).then(componentId => { - cy.get( - "[data-cy=dataProvider-prop-control] .spectrum-Picker" - ).should("not.have.class", "is-focused") - - // Pre populated. - cy.get("[data-cy=dataProvider-prop-control] .spectrum-Picker-label") - .contains(providerId) - .should("exist") - }) - } - cy.wait(1000) - cy.wrap(chartTypeLabels) - .each(label => { - return testFocusOnCreate(label) - }) - .then(() => { - cy.get(".nav-item") - .contains(providerId) - .click({ force: true }) - deleteSelectedComponent() - }) - }) - }) - - it("should replace the placeholder when a url is set on an image", () => { - cy.searchAndAddComponent("Image").then(imageId => { - cy.get("[data-cy=setting-_instanceName] input") - .clear() - .type(imageId) - .blur() - //return $("New Data Provider.Rows")[0]["Attachment"][0]["url"] - //No minio, so just enter something local that will not reslove - cy.get("[data-cy=url-prop-control] input[type=text]") - .type("cypress/fixtures/ghost.png") - .blur() - cy.getComponent(imageId) - .find(".component-placeholder") - .should("not.exist") - cy.getComponent(imageId).find(`img[alt=${imageId}]`).should("exist") - cy.get(".nav-item") - .contains(imageId) - .click({ force: true }) - deleteSelectedComponent() - }) - }) - - it("should add a markdown component.", () => { - cy.searchAndAddComponent("Markdown Viewer").then(markdownId => { - cy.get("[data-cy=setting-_instanceName] input") - .clear() - .type(markdownId) - .blur() - cy.get( - "[data-cy=value-prop-control] input[type=text].spectrum-Textfield-input" - ) - .type("# Hi") - .blur() - cy.getComponent(markdownId) - .find(".component-placeholder") - .should("not.exist") - cy.getComponent(markdownId) - .find(".editor-preview-full h1") - .contains("Hi") - cy.get(".nav-item") - .contains(markdownId) - .click({ force: true }) - deleteSelectedComponent() - }) - }) - - it("should direct the user when adding an Icon component.", () => { - cy.searchAndAddComponent("Icon").then(iconId => { - cy.get("[data-cy=setting-_instanceName] input") - .clear() - .type(iconId) - .blur() - cy.get("[data-cy=icon-prop-control] .spectrum-ActionButton").click() - cy.get("[data-cy=icon-popover].spectrum-Popover.is-open").within(() => { - cy.get(".search-input input").type("save").blur() - cy.get(".search-input button").click({ force: true }) - cy.get(".icon-area .icon-container").eq(0).click({ force: true }) - }) - cy.getComponent(iconId) - .find(".component-placeholder") - .should("not.exist") - cy.getComponent(iconId).find("i.ri-save-fill").should("exist") - cy.get(".nav-item") - .contains(iconId) - .click({ force: true }) - deleteSelectedComponent() - }) - }) - }) -}) diff --git a/packages/builder/cypress/integration/createScreen.spec.js b/packages/builder/cypress/integration/createScreen.spec.js deleted file mode 100644 index c4b237279d..0000000000 --- a/packages/builder/cypress/integration/createScreen.spec.js +++ /dev/null @@ -1,54 +0,0 @@ -import filterTests from "../support/filterTests" -const interact = require('../support/interact') - -filterTests(["smoke", "all"], () => { - context("Screen Tests", () => { - before(() => { - cy.login() - cy.createTestApp() - cy.navigateToFrontend() - }) - - it.skip("Should successfully create a screen", () => { - cy.createScreen("test") - cy.get(interact.BODY).within(() => { - cy.contains("/test").should("exist") - }) - }) - - it("Should update the url", () => { - cy.createScreen("test with spaces") - cy.get(interact.BODY).within(() => { - cy.contains("/test-with-spaces").should("exist") - }) - }) - - it.skip("should delete all screens then create first screen via button", () => { - cy.deleteAllScreens() - - cy.contains("Create first screen").click() - cy.get(interact.BODY, { timeout: 2000 }).should('contain', '/home') - }) - - it("Should create and filter screens by access level", () => { - const accessLevels = ["Basic", "Admin", "Public", "Power"] - - for (const access of accessLevels){ - // Create screen with specified access level - cy.createScreen(access, access) - // Filter by access level and confirm screen visible - cy.filterScreensAccessLevel(access) - cy.get(interact.BODY).within(() => { - cy.get(interact.NAV_ITEM).should('contain', access.toLowerCase()) - }) - } - - // Filter by All screens - Confirm all screens visible - cy.filterScreensAccessLevel("All screens") - cy.get(interact.BODY).should('contain', accessLevels[0]) - .and('contain', accessLevels[1]) - .and('contain', accessLevels[2]) - .and('contain', accessLevels[3]) - }) - }) -}) diff --git a/packages/builder/cypress/integration/createTable.spec.js b/packages/builder/cypress/integration/createTable.spec.js deleted file mode 100644 index 1c3e69a36b..0000000000 --- a/packages/builder/cypress/integration/createTable.spec.js +++ /dev/null @@ -1,112 +0,0 @@ -import filterTests from "../support/filterTests" -const interact = require('../support/interact') - -filterTests(["smoke", "all"], () => { - xcontext("Create a Table", () => { - before(() => { - cy.login() - cy.createTestApp() - }) - - it("should create a new Table", () => { - cy.createTable("dog") - // Check if Table exists - cy.get(interact.TABLE_TITLE_H1, { timeout: 1000 }).should("have.text", "dog") - }) - - it("adds a new column to the table", () => { - cy.addColumn("dog", "name", "Text") - cy.contains("name").should("be.visible") - }) - - it("creates a row in the table", () => { - cy.addRow(["Rover"]) - cy.contains("Rover").should("be.visible") - }) - - it("updates a column on the table", () => { - cy.get(interact.TABLE_TITLE).click() - cy.get(interact.SPECTRUM_TABLE_EDIT).click() - cy.get(interact.MODAL_INNER_WRAPPER).within(() => { - - cy.get("input").eq(0).type("updated", { force: true }) - // Unset table display column - cy.get(interact.SPECTRUM_SWITCH_INPUT).eq(1).click() - cy.contains("Save Column").click() - }) - cy.contains("nameupdated ").should("contain", "nameupdated") - }) - - it("edits a row", () => { - cy.contains("button", "Edit").click({ force: true }) - cy.wait(500) - cy.get(interact.SPECTRUM_MODAL_INPUT).clear() - cy.get(interact.SPECTRUM_MODAL_INPUT).type("Updated") - cy.contains("Save").click() - cy.contains("Updated").should("have.text", "Updated") - }) - - it("deletes a row", () => { - cy.get(interact.SPECTRUM_CHECKBOX_INPUT).check({ force: true }) - cy.contains("Delete 1 row").click() - cy.get(interact.SPECTRUM_MODAL).contains("Delete").click() - cy.contains("RoverUpdated").should("not.exist") - }) - - if (Cypress.env("TEST_ENV")) { - // No Pagination in CI - Test env only for the next two tests - xit("Adds 15 rows and checks pagination", () => { - // 10 rows per page, 15 rows should create 2 pages within table - const totalRows = 16 - for (let i = 1; i < totalRows; i++) { - cy.addRow([i]) - } - cy.reload() - cy.get(interact.SPECTRUM_PAGINATION, { timeout: 2000 }).within(() => { - cy.get(interact.SPECTRUM_ACTION_BUTTON).eq(1).click() - }) - cy.get(interact.SPECTRUM_PAGINATION).within(() => { - cy.get(interact.SPECTRUM_BODY_SECOND).contains("Page 2") - }) - }) - - xit("Deletes rows and checks pagination", () => { - // Delete rows, removing second page from table - cy.get(interact.SPECTRUM_CHECKBOX_INPUT).check({ force: true }) - cy.get(interact.POPOVERS).within(() => { - cy.get(interact.SPECTRUM_BUTTON).click({ force: true }) - }) - cy.get(interact.SPECTRUM_DIALOG_GRID).contains("Delete").click({ force: true }) - - // Confirm table only has one page - cy.get(interact.SPECTRUM_PAGINATION, { timeout: 1000 }).within(() => { - cy.get(interact.SPECTRUM_ACTION_BUTTON).eq(1).should("not.be.enabled") - }) - }) - } - - it("deletes a column", () => { - const columnName = "nameupdated" - cy.get(interact.TABLE_TITLE).click() - cy.get(interact.SPECTRUM_TABLE_EDIT).click() - cy.contains("Delete").click() - cy.get(interact.DELETE_COLUMN_CONFIRM).type(columnName) - cy.contains("Delete Column").click() - cy.contains("nameupdated").should("not.exist") - }) - - it("deletes a table", () => { - cy.get(interact.NAV_ITEM) - .contains("dog") - .parents(interact.NAV_ITEM) - .first() - .within(() => { - cy.get(interact.ACTION_SPECTRUM_ICON).click({ force: true }) - }) - cy.get(interact.SPECTRUM_MENU_CHILD2).click() - cy.get(interact.DELETE_TABLE_CONFIRM).type("dog") - cy.contains("Delete Table").click() - cy.contains("dog").should("not.exist") - }) - }) -}) diff --git a/packages/builder/cypress/integration/createView.spec.js b/packages/builder/cypress/integration/createView.spec.js deleted file mode 100644 index 9adc486f70..0000000000 --- a/packages/builder/cypress/integration/createView.spec.js +++ /dev/null @@ -1,157 +0,0 @@ -import filterTests from "../support/filterTests" -const interact = require('../support/interact') - -filterTests(['smoke', 'all'], () => { - context("Create a View", () => { - before(() => { - cy.login() - cy.createTestApp() - cy.createTable("data") - cy.addColumn("data", "group", "Text") - cy.addColumn("data", "age", "Number") - cy.addColumn("data", "rating", "Number") - - // 6 Rows - cy.addRow(["Students", 25, 1]) - cy.addRow(["Students", 20, 3]) - cy.addRow(["Students", 18, 6]) - cy.addRow(["Students", 25, 2]) - cy.addRow(["Teachers", 49, 5]) - cy.addRow(["Teachers", 36, 3]) - }) - - it("creates a view", () => { - cy.contains("Create view").click() - cy.get(interact.MODAL_INNER_WRAPPER).within(() => { - cy.get("input").type("Test View") - cy.get("button").contains("Create View").click({ force: true }) - }) - cy.get(interact.TABLE_TITLE_H1).contains("Test View") - cy.get(interact.TITLE).then($headers => { - expect($headers).to.have.length(3) - const headers = Array.from($headers).map(header => - header.textContent.trim() - ) - expect(removeSpacing(headers)).to.deep.eq(["group", "age", "rating"]) - }) - }) - - it("filters the view by age over 10", () => { - cy.contains("Filter").click() - cy.contains("Add Filter").click() - - cy.get(interact.MODAL_INNER_WRAPPER).within(() => { - cy.get(interact.SPECTRUM_PICKER_LABEL).eq(0).click() - cy.contains("age").click({ force: true }) - - cy.get(interact.SPECTRUM_PICKER_LABEL).eq(1).click() - cy.contains("More Than").click({ force: true }) - - cy.get("input").type(18) - cy.contains("Save").click() - }) - - cy.get(interact.SPECTRUM_TABLE_ROW).get($values => { - expect($values).to.have.length(5) - }) - }) - - it("creates a stats calculation view based on age", () => { - cy.wait(1000) - cy.contains("Calculate").click() - cy.get(interact.MODAL_INNER_WRAPPER).within(() => { - cy.get(interact.SPECTRUM_PICKER_LABEL).eq(0).click() - cy.contains("Statistics").click() - - cy.get(interact.SPECTRUM_PICKER_LABEL).eq(1).click() - cy.contains("age").click({ force: true }) - - cy.get(interact.SPECTRUM_BUTTON).contains("Save").click({ force: true }) - }) - - cy.wait(1000) - cy.get(interact.TITLE).then($headers => { - expect($headers).to.have.length(7) - const headers = Array.from($headers).map(header => - header.textContent.trim() - ) - expect(removeSpacing(headers)).to.deep.eq([ - "field", - "sum", - "min", - "max", - "count", - "sumsqr", - "avg", - ]) - }) - cy.get(interact.SPECTRUM_TABLE_CELL).then($values => { - let values = Array.from($values).map(header => header.textContent.trim()) - expect(values).to.deep.eq(["age", "155", "20", "49", "5", "5347", "31"]) - }) - }) - - it("groups the view by group", () => { - cy.contains("Group by").click() - cy.get(interact.MODAL_INNER_WRAPPER).within(() => { - cy.get(interact.SPECTRUM_PICKER_LABEL).eq(0).click() - cy.contains("group").click() - cy.contains("Save").click() - }) - cy.wait(1000) - cy.contains("Students").should("be.visible") - cy.contains("Teachers").should("be.visible") - - cy.get(interact.SPECTRUM_TABLE_CELL).then($values => { - let values = Array.from($values).map(header => header.textContent.trim()) - expect(values).to.deep.eq([ - "Students", - "70", - "20", - "25", - "3", - "1650", - "23.333333333333332", - "Teachers", - "85", - "36", - "49", - "2", - "3697", - "42.5", - ]) - }) - }) - - it("renames a view", () => { - cy.contains(interact.NAV_ITEM, "Test View") - .find(".actions .icon.open-popover") - .click({ force: true }) - cy.get(interact.SPECTRUM_MENU_ITEM_LABEL).contains("Edit").click() - cy.get(interact.MODAL_INNER_WRAPPER).within(() => { - cy.get("input").type(" Updated") - cy.contains("Save").click() - }) - cy.wait(1000) - cy.contains("Test View Updated").should("be.visible") - }) - - it("deletes a view", () => { - cy.contains(interact.NAV_ITEM, "Test View Updated") - .find(".actions .icon.open-popover") - .click({ force: true }) - cy.contains("Delete").click() - cy.contains("Delete View").click() - cy.wait(500) - cy.contains("TestView Updated").should("not.exist") - }) - }) - - function removeSpacing(headers) { - let newHeaders = [] - for (let header of headers) { - newHeaders.push(header.replace(/\s\s+/g, " ")) - } - return newHeaders - } -}) diff --git a/packages/builder/cypress/integration/customThemingProperties.spec.js b/packages/builder/cypress/integration/customThemingProperties.spec.js deleted file mode 100644 index e9de0985d0..0000000000 --- a/packages/builder/cypress/integration/customThemingProperties.spec.js +++ /dev/null @@ -1,86 +0,0 @@ -import filterTests from "../support/filterTests" - -filterTests(['all'], () => { - xcontext("Custom Theming Properties", () => { - before(() => { - cy.login() - cy.createTestApp() - cy.navigateToFrontend() - }) - - /* Default Values: - Button roundness = Large - Accent colour = Blue 600 - Accent colour (hover) = Blue 500 - Navigation bar background colour = Gray 100 - Navigation bar text colour = Gray 800 */ - it("should reset the color property values", () => { - // Open Theme modal and change colours - cy.get(".spectrum-ActionButton-label").contains("Theme").click() - cy.get(".spectrum-Picker").contains("Large").click() - .parents() - .get(".spectrum-Menu-itemLabel").contains("None").click() - changeThemeColors() - // Reset colours - cy.get(".spectrum-Button-label").contains("Reset").click({force: true}) - // Check values have reset - checkThemeColorDefaults() - }) - - /* Button Roundness Values: - None = 0 - Small = 4px - Medium = 8px - Large = 16px */ - it("should test button roundness", () => { - const buttonRoundnessValues = ["0", "4px", "8px", "16px"] - // Add button, change roundness and confirm value - cy.addComponent("Button", null).then((componentId) => { - buttonRoundnessValues.forEach(function (item, index){ - cy.get(".spectrum-ActionButton-label").contains("Theme").click() - cy.get(".setting").contains("Button roundness").parent() - .get(".select-wrapper").click() - cy.get(".spectrum-Popover").find('li').eq(index).click() - cy.get(".spectrum-Button").contains("View changes").click({force: true}) - cy.reload() - cy.getComponent(componentId) - .parents(".svelte-xiqd1c").eq(0).should('have.attr', 'style').and('contains', `--buttonBorderRadius:${item}`) - }) - }) - }) - - const changeThemeColors = () => { - // Changes the theme colours - cy.get(".spectrum-FieldLabel").contains("Accent color") - .parent().find(".container.svelte-z3cm5a").click() - .find('[title="Red 400"]').click() - cy.get(".spectrum-FieldLabel").contains("Accent color (hover)") - .parent().find(".container.svelte-z3cm5a").click() - .find('[title="Orange 400"]').click() - cy.get(".spectrum-FieldLabel").contains("Navigation bar background color") - .parent().find(".container.svelte-z3cm5a").click() - .find('[title="Yellow 400"]').click() - cy.get(".spectrum-FieldLabel").contains("Navigation bar text color") - .parent().find(".container.svelte-z3cm5a").click() - .find('[title="Green 400"]').click() - } - - const checkThemeColorDefaults = () => { - cy.get(".spectrum-FieldLabel").contains("Accent color") - .parent().find(".container.svelte-z3cm5a").click() - .get('[title="Blue 600"]').children().find('[aria-label="Checkmark"]') - cy.get(".spectrum-Dialog-grid").click() - cy.get(".spectrum-FieldLabel").contains("Accent color (hover)") - .parent().find(".container.svelte-z3cm5a").click() - .get('[title="Blue 500"]').children().find('[aria-label="Checkmark"]') - cy.get(".spectrum-Dialog-grid").click() - cy.get(".spectrum-FieldLabel").contains("Navigation bar background color") - .parent().find(".container.svelte-z3cm5a").click() - .get('[title="Gray 100"]').children().find('[aria-label="Checkmark"]') - cy.get(".spectrum-Dialog-grid").click() - cy.get(".spectrum-FieldLabel").contains("Navigation bar text color") - .parent().find(".container.svelte-z3cm5a").click() - .get('[title="Gray 800"]').children().find('[aria-label="Checkmark"]') - } - }) -}) diff --git a/packages/builder/cypress/integration/datasources/datasourceWizard.spec.js b/packages/builder/cypress/integration/datasources/datasourceWizard.spec.js deleted file mode 100644 index 837a433951..0000000000 --- a/packages/builder/cypress/integration/datasources/datasourceWizard.spec.js +++ /dev/null @@ -1,42 +0,0 @@ -import filterTests from "../../support/filterTests" - -filterTests(['all'], () => { - xcontext("Datasource Wizard", () => { - if (Cypress.env("TEST_ENV")) { - before(() => { - cy.login() - cy.createTestApp() - }) - - it("should navigate in and out of a datasource via wizard", () => { - // Select PostgreSQL and add config (without fetch) - const datasource = "Oracle" - cy.selectExternalDatasource(datasource) - cy.addDatasourceConfig(datasource, true) - - // Navigate back within datasource wizard - cy.get(".spectrum-Dialog-grid").within(() => { - cy.get(".spectrum-Button").contains("Back").click({ force: true }) - }) - - // Select PostgreSQL datasource again - cy.get(".item-list", { timeout: 1000 }).contains(datasource).click() - cy.get(".spectrum-Dialog-grid").within(() => { - cy.get(".spectrum-Button").contains("Continue").click({ force: true }) - }) - - // Fetch tables after selection - // Previously entered config should not have been saved - // Config is back to default values - // Modal will close and provide 500 error - cy.intercept('**/datasources').as('datasourceConnection') - cy.get(".spectrum-Dialog-grid").within(() => { - cy.get(".spectrum-Button").contains("Save and fetch tables").click({ force: true }) - }) - cy.wait("@datasourceConnection") - cy.get("@datasourceConnection").its('response.body') - .should('have.property', 'status', 500) - }) - } - }) -}) diff --git a/packages/builder/cypress/integration/datasources/mySql.spec.js b/packages/builder/cypress/integration/datasources/mySql.spec.js deleted file mode 100644 index 11370a9bf3..0000000000 --- a/packages/builder/cypress/integration/datasources/mySql.spec.js +++ /dev/null @@ -1,229 +0,0 @@ -import filterTests from "../../support/filterTests" - -filterTests(["all"], () => { - xcontext("MySQL Datasource Testing", () => { - if (Cypress.env("TEST_ENV")) { - before(() => { - cy.login() - cy.createTestApp() - }) - const datasource = "MySQL" - const queryName = "Cypress Test Query" - const queryRename = "CT Query Rename" - - it("Should add MySQL datasource without configuration", () => { - // Select MySQL datasource - cy.selectExternalDatasource(datasource) - // Attempt to fetch tables without applying configuration - cy.intercept("**/datasources").as("datasource") - cy.get(".spectrum-Button") - .contains("Save and fetch tables") - .click({ force: true }) - cy.wait(500) - // Intercept Request after button click & apply assertions - cy.wait("@datasource") - cy.get("@datasource") - .its("response.body") - .should( - "have.property", - "message", - "connect ECONNREFUSED 127.0.0.1:3306" - ) - cy.get("@datasource") - .its("response.body") - .should("have.property", "status", 500) - cy.get(".spectrum-Button").contains("Skip table fetch").click({ force: true }) - }) - - it("should add MySQL datasource and fetch tables", () => { - // Add & configure MySQL datasource - cy.selectExternalDatasource(datasource) - cy.intercept("**/datasources").as("datasource") - cy.addDatasourceConfig(datasource) - // Check response from datasource after adding configuration - cy.wait("@datasource") - cy.get("@datasource").its("response.statusCode").should("eq", 200) - // Confirm fetch tables was successful - cy.get(".spectrum-Table") - .eq(0) - .find(".spectrum-Table-row") - .its("length") - .should("be.gt", 0) - }) - - it("should check table fetching error", () => { - // MySQL test datasource contains tables without primary keys - cy.get(".spectrum-InLineAlert") - .should("contain", "Error fetching tables") - .and("contain", "No primary key constraint found") - }) - - it("should define a One relationship type", () => { - // Select relationship type & configure - cy.get(".spectrum-Button") - .contains("Define relationship") - .click({ force: true }) - cy.get(".spectrum-Dialog-grid").within(() => { - cy.get(".spectrum-Picker").eq(0).click() - cy.get(".spectrum-Popover").contains("One").click() - cy.get(".spectrum-Picker").eq(1).click() - cy.get(".spectrum-Popover").contains("REGIONS").click() - cy.get(".spectrum-Picker").eq(2).click() - cy.get(".spectrum-Popover").contains("REGION_ID").click() - cy.get(".spectrum-Picker").eq(3).click() - cy.get(".spectrum-Popover").contains("COUNTRIES").click() - cy.get(".spectrum-Picker").eq(4).click() - cy.get(".spectrum-Popover").contains("REGION_ID").click() - }) - // Save relationship & reload page - cy.get(".spectrum-ButtonGroup").within(() => { - cy.get(".spectrum-Button").contains("Save").click({ force: true }) - }) - cy.reload() - - // Confirm table length & column name - cy.get(".spectrum-Table") - .eq(1) - .find(".spectrum-Table-row") - .its("length") - .should("eq", 1) - cy.get(".spectrum-Table-cell").should("contain", "COUNTRIES to REGIONS") - }) - - it("should define a Many relationship type", () => { - // Select relationship type & configure - cy.get(".spectrum-Button") - .contains("Define relationship") - .click({ force: true }) - cy.get(".spectrum-Dialog-grid").within(() => { - cy.get(".spectrum-Picker").eq(0).click() - cy.get(".spectrum-Popover").contains("Many").click() - cy.get(".spectrum-Picker").eq(1).click() - cy.get(".spectrum-Popover").contains("LOCATIONS").click() - cy.get(".spectrum-Picker").eq(2).click() - cy.get(".spectrum-Popover").contains("REGIONS").click() - cy.get(".spectrum-Picker").eq(3).click() - cy.get(".spectrum-Popover").contains("COUNTRIES").click() - cy.get(".spectrum-Picker").eq(4).click() - cy.get(".spectrum-Popover").contains("COUNTRY_ID").click() - cy.get(".spectrum-Picker").eq(5).click() - cy.get(".spectrum-Popover").contains("REGION_ID").click() - // Save relationship & reload page - cy.get(".spectrum-Button").contains("Save").click({ force: true }) - cy.reload() - cy.wait(1000) - }) - // Confirm table length & relationship name - cy.get(".spectrum-Table", { timeout: 1000 }) - .eq(1) - .find(".spectrum-Table-row") - .its("length") - .should("eq", 2) - cy.get(".spectrum-Table-cell").should( - "contain", - "LOCATIONS through COUNTRIES → REGIONS" - ) - }) - - it("should delete relationships", () => { - // Delete both relationships - cy.get(".spectrum-Table") - .eq(1) - .find(".spectrum-Table-row") - .its("length") - .then(len => { - for (let i = 0; i < len; i++) { - cy.get(".spectrum-Table") - .eq(1) - .within(() => { - cy.get(".spectrum-Table-cell").eq(0).click({ force: true }) - }) - cy.get(".spectrum-Dialog-grid", { timeout: 500 }).within(() => { - cy.get(".spectrum-Button") - .contains("Delete") - .click({ force: true }) - }) - cy.reload() - cy.wait(500) - } - // Confirm relationships no longer exist - cy.get(".spectrum-Body").should( - "contain", - "No relationships configured" - ) - }) - }) - - it("should add a query", () => { - // Add query - cy.get(".spectrum-Button").contains("Add query").click({ force: true }) - cy.get(".spectrum-Form-item") - .eq(0) - .within(() => { - cy.get("input").type(queryName) - }) - // Insert Query within Fields section - cy.get(".CodeMirror textarea") - .eq(0) - .type("SELECT * FROM books", { force: true }) - // Intercept query execution - cy.intercept("**/queries/preview").as("query") - cy.get(".spectrum-Button").contains("Run Query").click({ force: true }) - cy.wait(500) - cy.wait("@query") - // Assert against Status Code & Body - cy.get("@query").its("response.statusCode").should("eq", 200) - cy.get("@query").its("response.body").should("not.be.empty") - // Save query - cy.intercept("POST", "**/queries").as("saveQuery") - cy.get(".spectrum-Button").contains("Save Query").click({ force: true }) - cy.wait("@saveQuery") - cy.get("@saveQuery").its("response.statusCode").should("eq", 200) - cy.get(".nav-item").should("contain", queryName) - }) - - it("should duplicate a query", () => { - /// Get query nav item - QueryName - cy.get(".nav-item") - .contains(queryName) - .parent() - .within(() => { - cy.get(".spectrum-Icon").eq(1).click({ force: true }) - }) - // Select and confirm duplication - cy.get(".spectrum-Menu").contains("Duplicate").click() - cy.get(".nav-item").should("contain", queryName + " (1)") - }) - - it("should edit a query name", () => { - // Rename query - cy.get(".spectrum-Form-item") - .eq(0) - .within(() => { - cy.get("input").clear().type(queryRename) - }) - // Click on a nav item - cy.get(".nav-item").first().click() - // Confirm name change - cy.get(".nav-item").should("contain", queryRename) - }) - - it("should delete a query", () => { - // Get query nav item - QueryName - cy.get(".nav-item") - .contains(queryRename) - .parent() - .within(() => { - cy.get(".spectrum-Icon").eq(1).click({ force: true }) - }) - // Select Delete - cy.get(".spectrum-Menu").contains("Delete").click() - cy.get(".spectrum-Button") - .contains("Delete Query") - .click({ force: true }) - // Confirm deletion - cy.get(".nav-item", { timeout: 1000 }).should("not.contain", queryRename) - }) - } - }) -}) diff --git a/packages/builder/cypress/integration/datasources/oracle.spec.js b/packages/builder/cypress/integration/datasources/oracle.spec.js deleted file mode 100644 index ae1ca5cd75..0000000000 --- a/packages/builder/cypress/integration/datasources/oracle.spec.js +++ /dev/null @@ -1,229 +0,0 @@ -import filterTests from "../../support/filterTests" - -filterTests(["all"], () => { - xcontext("Oracle Datasource Testing", () => { - if (Cypress.env("TEST_ENV")) { - before(() => { - cy.login() - cy.createTestApp() - }) - const datasource = "Oracle" - const queryName = "Cypress Test Query" - const queryRename = "CT Query Rename" - - it("Should add Oracle datasource and skip table fetch", () => { - // Select Oracle datasource - cy.selectExternalDatasource(datasource) - // Skip table fetch - no config added - cy.get(".spectrum-Button") - .contains("Skip table fetch") - .click({ force: true }) - cy.wait(500) - // Confirm config contains localhost - cy.get(".spectrum-Textfield-input", { timeout: 500 }) - .eq(1) - .should("have.value", "localhost") - // Add another Oracle datasource, configure & skip table fetch - cy.selectExternalDatasource(datasource) - cy.addDatasourceConfig(datasource, true) - // Confirm config and no tables - cy.get(".spectrum-Textfield-input") - .eq(1) - .should("have.value", Cypress.env("oracle").HOST) - cy.get(".spectrum-Body").eq(2).should("contain", "No tables found.") - }) - - it("Should add Oracle datasource and fetch tables without configuration", () => { - // Select Oracle datasource - cy.selectExternalDatasource(datasource) - // Attempt to fetch tables without applying configuration - cy.intercept("**/datasources").as("datasource") - cy.get(".spectrum-Button") - .contains("Save and fetch tables") - .click({ force: true }) - // Intercept Request after button click & apply assertions - cy.wait("@datasource") - cy.get("@datasource") - .its("response.body") - .should("have.property", "status", 500) - cy.get(".spectrum-Button").contains("Skip table fetch").click({ force: true }) - }) - - xit("should add Oracle datasource and fetch tables", () => { - // Add & configure Oracle datasource - cy.selectExternalDatasource(datasource) - cy.intercept("**/datasources").as("datasource") - cy.addDatasourceConfig(datasource) - // Check response from datasource after adding configuration - cy.wait("@datasource") - cy.get("@datasource").its("response.statusCode").should("eq", 200) - // Confirm fetch tables was successful - cy.get(".spectrum-Table") - .eq(0) - .find(".spectrum-Table-row") - .its("length") - .should("be.gt", 0) - }) - - xit("should define a One relationship type", () => { - // Select relationship type & configure - cy.get(".spectrum-Button") - .contains("Define relationship") - .click({ force: true }) - cy.get(".spectrum-Dialog-grid").within(() => { - cy.get(".spectrum-Picker").eq(0).click() - cy.get(".spectrum-Popover").contains("One").click() - cy.get(".spectrum-Picker").eq(1).click() - cy.get(".spectrum-Popover").contains("REGIONS").click() - cy.get(".spectrum-Picker").eq(2).click() - cy.get(".spectrum-Popover").contains("REGION_ID").click() - cy.get(".spectrum-Picker").eq(3).click() - cy.get(".spectrum-Popover").contains("COUNTRIES").click() - cy.get(".spectrum-Picker").eq(4).click() - cy.get(".spectrum-Popover").contains("REGION_ID").click() - // Save relationship & reload page - cy.get(".spectrum-Button").contains("Save").click({ force: true }) - cy.reload() - }) - // Confirm table length & column name - cy.get(".spectrum-Table") - .eq(1) - .find(".spectrum-Table-row") - .its("length") - .should("eq", 1) - cy.get(".spectrum-Table-cell").should("contain", "COUNTRIES to REGIONS") - }) - - xit("should define a Many relationship type", () => { - // Select relationship type & configure - cy.get(".spectrum-Button") - .contains("Define relationship") - .click({ force: true }) - cy.get(".spectrum-Dialog-grid").within(() => { - cy.get(".spectrum-Picker").eq(0).click() - cy.get(".spectrum-Popover").contains("Many").click() - cy.get(".spectrum-Picker").eq(1).click() - cy.get(".spectrum-Popover").contains("LOCATIONS").click() - cy.get(".spectrum-Picker").eq(2).click() - cy.get(".spectrum-Popover").contains("REGIONS").click() - cy.get(".spectrum-Picker").eq(3).click() - cy.get(".spectrum-Popover").contains("COUNTRIES").click() - cy.get(".spectrum-Picker").eq(4).click() - cy.get(".spectrum-Popover").contains("COUNTRY_ID").click() - cy.get(".spectrum-Picker").eq(5).click() - cy.get(".spectrum-Popover").contains("REGION_ID").click() - // Save relationship & reload page - cy.get(".spectrum-Button").contains("Save").click({ force: true }) - cy.reload() - }) - // Confirm table length & relationship name - cy.get(".spectrum-Table") - .eq(1) - .find(".spectrum-Table-row") - .its("length") - .should("eq", 2) - cy.get(".spectrum-Table-cell").should( - "contain", - "LOCATIONS through COUNTRIES → REGIONS" - ) - }) - - xit("should delete relationships", () => { - // Delete both relationships - cy.get(".spectrum-Table") - .eq(1) - .find(".spectrum-Table-row") - .its("length") - .then(len => { - for (let i = 0; i < len; i++) { - cy.get(".spectrum-Table") - .eq(1) - .within(() => { - cy.get(".spectrum-Table-row").eq(0).click() - }) - cy.get(".spectrum-Dialog-grid", { timeout: 500 }).within(() => { - cy.get(".spectrum-Button") - .contains("Delete") - .click({ force: true }) - }) - cy.reload() - } - // Confirm relationships no longer exist - cy.get(".spectrum-Body").should( - "contain", - "No relationships configured" - ) - }) - }) - - xit("should add a query", () => { - // Add query - cy.get(".spectrum-Button").contains("Add query").click({ force: true }) - cy.get(".spectrum-Form-item") - .eq(0) - .within(() => { - cy.get("input").type(queryName) - }) - // Insert Query within Fields section - cy.get(".CodeMirror textarea") - .eq(0) - .type("SELECT * FROM JOBS", { force: true }) - // Intercept query execution - cy.intercept("**/queries/preview").as("query") - cy.get(".spectrum-Button").contains("Run Query").click({ force: true }) - cy.wait(500) - cy.wait("@query") - // Assert against Status Code & Body - cy.get("@query").its("response.statusCode").should("eq", 200) - cy.get("@query").its("response.body").should("not.be.empty") - // Save query - cy.get(".spectrum-Button").contains("Save Query").click({ force: true }) - cy.get(".nav-item").should("contain", queryName) - }) - - xit("should duplicate a query", () => { - // Get query nav item - cy.get(".nav-item") - .contains(queryName) - .parent() - .within(() => { - cy.get(".spectrum-Icon").eq(1).click({ force: true }) - }) - // Select and confirm duplication - cy.get(".spectrum-Menu").contains("Duplicate").click() - cy.get(".nav-item").should("contain", queryName + " (1)") - }) - - xit("should edit a query name", () => { - // Rename query - cy.get(".spectrum-Form-item") - .eq(0) - .within(() => { - cy.get("input").clear().type(queryRename) - }) - // Save query - cy.get(".spectrum-Button").contains("Save Query").click({ force: true }) - cy.get(".nav-item").should("contain", queryRename) - }) - - xit("should delete a query", () => { - // Get query nav item - QueryName - cy.get(".nav-item") - .contains(queryName) - .parent() - .within(() => { - cy.get(".spectrum-Icon").eq(1).click({ force: true }) - }) - - // Select Delete - cy.get(".spectrum-Menu").contains("Delete").click() - cy.get(".spectrum-Button") - .contains("Delete Query") - .click({ force: true }) - - // Confirm deletion - cy.get(".nav-item", { timeout: 1000 }).should("not.contain", queryName) - }) - } - }) -}) diff --git a/packages/builder/cypress/integration/datasources/postgreSql.spec.js b/packages/builder/cypress/integration/datasources/postgreSql.spec.js deleted file mode 100644 index e1aa0ff128..0000000000 --- a/packages/builder/cypress/integration/datasources/postgreSql.spec.js +++ /dev/null @@ -1,283 +0,0 @@ -import filterTests from "../../support/filterTests" - -filterTests(["all"], () => { - xcontext("PostgreSQL Datasource Testing", () => { - if (Cypress.env("TEST_ENV")) { - before(() => { - cy.login() - cy.createTestApp() - }) - const datasource = "PostgreSQL" - const queryName = "Cypress Test Query" - const queryRename = "CT Query Rename" - - xit("Should add PostgreSQL datasource without configuration", () => { - // Select PostgreSQL datasource - cy.selectExternalDatasource(datasource) - // Attempt to fetch tables without applying configuration - cy.intercept("**/datasources").as("datasource") - cy.get(".spectrum-Button") - .contains("Save and fetch tables") - .click({ force: true }) - // Intercept Request after button click & apply assertions - cy.wait("@datasource") - cy.get("@datasource") - .its("response.body") - .should("have.property", "status", 500) - cy.get(".spectrum-Button").contains("Skip table fetch").click({ force: true }) - }) - - it("should add PostgreSQL datasource and fetch tables", () => { - // Add & configure PostgreSQL datasource - cy.selectExternalDatasource(datasource) - cy.intercept("**/datasources").as("datasource") - cy.addDatasourceConfig(datasource) - // Check response from datasource after adding configuration - cy.wait("@datasource") - cy.get("@datasource").its("response.statusCode").should("eq", 200) - cy.wait(2000) - // Confirm fetch tables was successful - cy.get(".spectrum-Table") - .eq(0) - .find(".spectrum-Table-row") - .its("length") - .should("be.gt", 0) - }) - - it("should define a One relationship type", () => { - // Select relationship type & configure - cy.get(".spectrum-Button") - .contains("Define relationship") - .click({ force: true }) - cy.get(".spectrum-Dialog-grid").within(() => { - cy.get(".spectrum-Picker").eq(0).click() - cy.get(".spectrum-Popover").contains("One").click() - cy.get(".spectrum-Picker").eq(1).click() - cy.get(".spectrum-Popover").contains("REGIONS").click() - cy.get(".spectrum-Picker").eq(2).click() - cy.get(".spectrum-Popover").contains("REGION_ID").click() - cy.get(".spectrum-Picker").eq(3).click() - cy.get(".spectrum-Popover").contains("COUNTRIES").click() - cy.get(".spectrum-Picker").eq(4).click() - cy.get(".spectrum-Popover").contains("REGION_ID").click() - // Save relationship & reload page - cy.get(".spectrum-Button").contains("Save").click({ force: true }) - cy.reload() - }) - // Confirm table length & column name - cy.get(".spectrum-Table") - .eq(1) - .find(".spectrum-Table-row") - .its("length") - .should("eq", 1) - cy.get(".spectrum-Table-cell").should("contain", "COUNTRIES to REGIONS") - }) - - it("should define a Many relationship type", () => { - // Select relationship type & configure - cy.get(".spectrum-Button") - .contains("Define relationship") - .click({ force: true }) - cy.get(".spectrum-Dialog-grid").within(() => { - cy.get(".spectrum-Picker").eq(0).click() - cy.get(".spectrum-Popover").contains("Many").click() - cy.get(".spectrum-Picker").eq(1).click() - cy.get(".spectrum-Popover").contains("LOCATIONS").click() - cy.get(".spectrum-Picker").eq(2).click() - cy.get(".spectrum-Popover").contains("REGIONS").click() - cy.get(".spectrum-Picker").eq(3).click() - cy.get(".spectrum-Popover").contains("COUNTRIES").click() - cy.get(".spectrum-Picker").eq(4).click() - cy.get(".spectrum-Popover").contains("COUNTRY_ID").click() - cy.get(".spectrum-Picker").eq(5).click() - cy.get(".spectrum-Popover").contains("REGION_ID").click() - // Save relationship & reload page - cy.get(".spectrum-Button").contains("Save").click({ force: true }) - cy.reload() - }) - // Confirm table length & relationship name - cy.get(".spectrum-Table") - .eq(1) - .find(".spectrum-Table-row") - .its("length") - .should("eq", 2) - cy.get(".spectrum-Table-cell").should( - "contain", - "LOCATIONS through COUNTRIES → REGIONS" - ) - }) - - it("should delete a relationship", () => { - cy.get(".hierarchy-items-container").contains("PostgreSQL").click({ force: true }) - cy.reload() - // Delete one relationship - cy.get(".spectrum-Table") - .eq(1) - .within(() => { - cy.get(".spectrum-Table-cell").eq(0).click({ force: true }) - }) - cy.get(".spectrum-Dialog-grid", { timeout: 500 }).within(() => { - cy.get(".spectrum-Button").contains("Delete").click({ force: true }) - }) - cy.reload() - cy.wait(500) - // Confirm relationship was deleted - cy.get(".spectrum-Table") - .eq(1) - .find(".spectrum-Table-row") - .its("length") - .should("eq", 1) - }) - - it("should add a query", () => { - // Add query - cy.get(".spectrum-Button").contains("Add query").click({ force: true }) - cy.get(".spectrum-Form-item") - .eq(0) - .within(() => { - cy.get("input").type(queryName) - }) - // Insert Query within Fields section - cy.get(".CodeMirror textarea") - .eq(0) - .type("SELECT * FROM books", { force: true }) - // Intercept query execution - cy.intercept("**/queries/preview").as("query") - cy.get(".spectrum-Button").contains("Run Query").click({ force: true }) - cy.wait(500) - cy.wait("@query") - // Assert against Status Code & Body - cy.get("@query").its("response.statusCode").should("eq", 200) - cy.get("@query").its("response.body").should("not.be.empty") - // Save query - cy.intercept("**/queries").as("saveQuery") - cy.get(".spectrum-Button").contains("Save Query").click({ force: true }) - cy.wait("@saveQuery") - cy.get(".spectrum-Tabs-content", { timeout: 2000 }).should("contain", queryName) - }) - - it("should switch to schema with no tables", () => { - // Switch Schema - To one without any tables - cy.get(".hierarchy-items-container").contains("PostgreSQL").click({ force: true }) - switchSchema("randomText") - - // No tables displayed - cy.get(".spectrum-Body", { timeout: 10000 }).eq(2, { timeout: 10000 }).should("contain", "No tables found") - - // Previously created query should be visible - cy.get(".spectrum-Table").should("contain", queryName) - }) - - it("should switch schemas", () => { - // Switch schema - To one with tables - switchSchema("1") - - // Confirm tables exist - Check for specific one - cy.get(".spectrum-Table", { timeout: 20000 }).eq(0).should("contain", "test") - cy.get(".spectrum-Table") - .eq(0) - .find(".spectrum-Table-row") - .its("length") - .should("eq", 1) - - // Confirm specific table visible within left nav bar - cy.get(".hierarchy-items-container").should("contain", "test") - - // Switch back to public schema - switchSchema("public") - - // Confirm tables exist - again - cy.get(".spectrum-Table", { timeout: 20000 }).eq(0).should("contain", "REGIONS") - cy.get(".spectrum-Table") - .eq(0) - .find(".spectrum-Table-row") - .its("length") - .should("be.gt", 1) - - // Confirm specific table visible within left nav bar - cy.get(".hierarchy-items-container").should("contain", "REGIONS") - - // No relationships and one query - cy.get(".spectrum-Body") - .eq(3) - .should("contain", "No relationships configured.") - cy.get(".spectrum-Table").eq(1).should("contain", queryName) - }) - - it("should duplicate a query", () => { - // Locate previously created query - cy.get(".nav-item") - .contains(queryName) - .siblings(".actions") - .within(() => { - cy.get(".spectrum-Icon").click({ force: true }) - }) - // Select and confirm duplication - cy.get(".spectrum-Menu").contains("Duplicate").click() - cy.get(".nav-item").should("contain", queryName + " (1)") - }) - - it("should edit a query name", () => { - // Access query - cy.get(".hierarchy-items-container", { timeout: 2000 }) - //.contains(queryName + " (1)") - .contains(queryName) - .click({ force: true }) - - // Rename query - cy.wait(1000) - cy.get(".spectrum-Form-item", { timeout: 2000 }) - .eq(0) - .within(() => { - cy.get("input").clear().type(queryRename) - }) - - // Click on a nav item and confirm name change - cy.get(".nav-item").first().click() - // Confirm name change - cy.get(".nav-item").should("contain", queryRename) - }) - - it("should delete a query", () => { - // Get query nav item - QueryName - cy.get(".nav-item") - .contains(queryRename) - .parent() - .within(() => { - cy.get(".spectrum-Icon").eq(1).click({ force: true }) - }) - // Select Delete - cy.get(".spectrum-Menu").contains("Delete").click() - cy.get(".spectrum-Button") - .contains("Delete Query") - .click({ force: true }) - // Confirm deletion - cy.reload() - cy.get(".nav-item", { timeout: 30000 }).contains(datasource).click({ force: true }) - cy.get(".nav-item", { timeout: 1000 }).should("not.contain", queryRename) - }) - - const switchSchema = schema => { - // Edit configuration - Change Schema - cy.get(".spectrum-Textfield") - .eq(6) - .within(() => { - cy.get("input").clear().type(schema) - }) - // Save configuration & fetch - cy.get(".spectrum-Button").contains("Save").click({ force: true }) - cy.get(".spectrum-Button") - .contains("Fetch tables") - .click({ force: true }) - // Click fetch tables again within modal - cy.get(".spectrum-Dialog-grid").within(() => { - cy.get(".spectrum-Button") - .contains("Fetch tables") - .click({ force: true }) - }) - cy.reload() - cy.wait(1000) - } - } - }) -}) diff --git a/packages/builder/cypress/integration/datasources/rest.spec.js b/packages/builder/cypress/integration/datasources/rest.spec.js deleted file mode 100644 index 7f715ae50c..0000000000 --- a/packages/builder/cypress/integration/datasources/rest.spec.js +++ /dev/null @@ -1,45 +0,0 @@ -import filterTests from "../../support/filterTests" - -filterTests(["smoke", "all"], () => { - xcontext("REST Datasource Testing", () => { - before(() => { - cy.login() - cy.createTestApp() - }) - - const datasource = "REST" - const restUrl = "https://api.openbrewerydb.org/breweries" - - it("Should add REST datasource with incorrect API", () => { - // Select REST datasource - cy.selectExternalDatasource(datasource) - // Enter incorrect api & attempt to send query - cy.get(".query-buttons", { timeout: 1000 }).contains("Add query").click({ force: true }) - cy.intercept("**/preview").as("queryError") - cy.get("input").clear().type("random text") - cy.get(".spectrum-Button").contains("Send").click({ force: true }) - // Intercept Request after button click & apply assertions - cy.wait("@queryError") - cy.get("@queryError") - .its("response.body") - .should("have.property", "message", "Invalid URL: http://random text") - cy.get("@queryError") - .its("response.body") - .should("have.property", "status", 400) - }) - - it("should add and configure a REST datasource", () => { - // Select REST datasource and create query - cy.selectExternalDatasource(datasource) - cy.wait(500) - // createRestQuery confirms query creation - cy.createRestQuery("GET", restUrl, "/breweries") - // Confirm status code response within REST datasource - cy.get(".stats", { timeout: 1000 }).within(() => { - cy.get(".spectrum-FieldLabel") - .eq(0) - .should("contain", 200) - }) - }) - }) -}) diff --git a/packages/builder/cypress/integration/queryLevelTransformers.spec.js b/packages/builder/cypress/integration/queryLevelTransformers.spec.js deleted file mode 100644 index d16f8075f9..0000000000 --- a/packages/builder/cypress/integration/queryLevelTransformers.spec.js +++ /dev/null @@ -1,140 +0,0 @@ -import filterTests from "../support/filterTests" -const interact = require("../support/interact") - -filterTests(["smoke", "all"], () => { - context("Query Level Transformers", () => { - before(() => { - cy.login() - cy.createTestApp() - }) - - it("should write a transformer function", () => { - // Add REST datasource - contains API for breweries - const datasource = "REST" - const restUrl = "https://api.openbrewerydb.org/breweries" - cy.selectExternalDatasource(datasource) - cy.createRestQuery("GET", restUrl, "/breweries") - cy.get(interact.SPECTRUM_TABS_ITEM).contains("Transformer").click() - // Get Transformer Function from file - cy.readFile("cypress/support/queryLevelTransformerFunction.js").then( - transformerFunction => { - cy.get(interact.CODEMIRROR_TEXTAREA) - // Highlight current text and overwrite with file contents - .type(Cypress.platform === "darwin" ? "{cmd}a" : "{ctrl}a", { - force: true, - }) - .type(transformerFunction, { parseSpecialCharSequences: false }) - } - ) - // Send Query - cy.intercept("**/queries/preview").as("query") - cy.get(interact.SPECTRUM_BUTTON).contains("Send").click({ force: true }) - cy.wait("@query") - // Assert against Status Code, body, & body rows - cy.get("@query").its("response.statusCode").should("eq", 200) - cy.get("@query").its("response.body").should("not.be.empty") - cy.get("@query").its("response.body.rows").should("not.be.empty") - }) - - it("should add data to the previous query", () => { - // Add REST datasource - contains API for breweries - const datasource = "REST" - const restUrl = "https://api.openbrewerydb.org/breweries" - cy.selectExternalDatasource(datasource) - cy.createRestQuery("GET", restUrl, "/breweries") - cy.get(interact.SPECTRUM_TABS_ITEM).contains("Transformer").click() - // Get Transformer Function with Data from file - cy.readFile( - "cypress/support/queryLevelTransformerFunctionWithData.js" - ).then(transformerFunction => { - //console.log(transformerFunction[1]) - cy.get(interact.CODEMIRROR_TEXTAREA) - // Highlight current text and overwrite with file contents - .type(Cypress.platform === "darwin" ? "{cmd}a" : "{ctrl}a", { - force: true, - }) - .type(transformerFunction, { parseSpecialCharSequences: false }) - }) - // Send Query - cy.intercept("**/queries/preview").as("query") - cy.get(interact.SPECTRUM_BUTTON).contains("Send").click({ force: true }) - cy.wait("@query") - // Assert against Status Code, body, & body rows - cy.get("@query").its("response.statusCode").should("eq", 200) - cy.get("@query").its("response.body").should("not.be.empty") - cy.get("@query").its("response.body.rows").should("not.be.empty") - }) - - it("should run an invalid query within the transformer section", () => { - // Add REST datasource - contains API for breweries - const datasource = "REST" - const restUrl = "https://api.openbrewerydb.org/breweries" - cy.selectExternalDatasource(datasource) - cy.createRestQuery("GET", restUrl, "/breweries") - cy.get(interact.SPECTRUM_TABS_ITEM).contains("Transformer").click() - // Clear the code box and add "test" - cy.get(interact.CODEMIRROR_TEXTAREA) - .type(Cypress.platform === "darwin" ? "{cmd}a" : "{ctrl}a", { - force: true, - }) - .type("test") - // Run Query and intercept - cy.intercept("**/preview").as("queryError") - cy.get(interact.SPECTRUM_BUTTON).contains("Send").click({ force: true }) - cy.wait("@queryError") - cy.wait(500) - // Assert against message and status for the query error - cy.get("@queryError") - .its("response.body") - .should("have.property", "message", "test is not defined") - cy.get("@queryError") - .its("response.body") - .should("have.property", "status", 400) - }) - - xit("should run an invalid query via POST request", () => { - // POST request with transformer as null - cy.request({ - method: "POST", - url: `${Cypress.config().baseUrl}/api/queries/`, - body: { - fields: { headers: {}, queryString: null, path: null }, - parameters: [], - schema: {}, - name: "test", - queryVerb: "read", - transformer: null, - datasourceId: "test", - }, - // Expected 400 error - Transformer must be a string - failOnStatusCode: false, - }).then(response => { - expect(response.status).to.equal(400) - expect(response.body.message).to.include( - 'Invalid body - "transformer" must be a string' - ) - }) - }) - - xit("should run an empty query", () => { - // POST request with Transformer as an empty string - cy.request({ - method: "POST", - url: `${Cypress.config().baseUrl}/api/queries/preview`, - body: { - fields: { headers: {}, queryString: null, path: null }, - queryVerb: "read", - transformer: "", - datasourceId: "test", - }, - // Expected 400 error - Transformer is not allowed to be empty - failOnStatusCode: false, - }).then(response => { - expect(response.status).to.equal(400) - expect(response.body.message).to.include( - 'Invalid body - "transformer" is not allowed to be empty' - ) - }) - }) - }) -}) diff --git a/packages/builder/cypress/integration/renameAnApplication.spec.js b/packages/builder/cypress/integration/renameAnApplication.spec.js deleted file mode 100644 index 6e432e476b..0000000000 --- a/packages/builder/cypress/integration/renameAnApplication.spec.js +++ /dev/null @@ -1,112 +0,0 @@ -import filterTests from "../support/filterTests" -const interact = require("../support/interact") - -filterTests(["all"], () => { - xcontext("Rename an App", () => { - beforeEach(() => { - cy.login() - cy.createTestApp() - }) - - it("should rename an unpublished application", () => { - const appName = "Cypress Tests" - const appRename = "Cypress Renamed" - // Rename app, Search for app, Confirm name was changed - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 }) - renameApp(appName, appRename) - cy.reload() - cy.searchForApplication(appRename) - cy.get(interact.APP_TABLE).find(interact.TITLE).should("have.length", 1) - cy.applicationInAppTable(appRename) - // Set app name back to Cypress Tests - cy.reload() - renameApp(appRename, appName) - }) - - xit("Should rename a published application", () => { - // It is not possible to rename a published application - const appName = "Cypress Tests" - const appRename = "Cypress Renamed" - // Publish the app - cy.get(interact.TOP_RIGHT_NAV) - cy.get(interact.SPECTRUM_BUTTON) - .contains("Publish") - .click({ force: true }) - cy.get(interact.SPECTRUM_DIALOG_GRID).within(() => { - // Click publish again within the modal - cy.get(interact.SPECTRUM_BUTTON) - .contains("Publish") - .click({ force: true }) - }) - // Rename app, Search for app, Confirm name was changed - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 }) - renameApp(appName, appRename, true) - cy.get(interact.APP_TABLE).find(interact.WRAPPER).should("have.length", 1) - cy.applicationInAppTable(appRename) - }) - - it("Should try to rename an application to have no name", () => { - const appName = "Cypress Tests" - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 }) - renameApp(appName, " ", false, true) - // Close modal and confirm name has not been changed - cy.get(interact.SPECTRUM_DIALOG_GRID, { timeout: 1000 }).contains("Cancel").click() - cy.applicationInAppTable(appName) - }) - - xit("Should create two applications with the same name", () => { - // It is not possible to have applications with the same name - const appName = "Cypress Tests" - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 }) - cy.get(interact.SPECTRUM_BUTTON), { timeout: 500 } - .contains("Create app") - .click({ force: true }) - cy.contains(/Start from scratch/).click() - cy.get(interact.SPECTRUM_MODAL).within(() => { - cy.get("input").eq(0).type(appName) - cy.get(interact.SPECTRUM_BUTTON_GROUP) - .contains("Create app") - .click({ force: true }) - cy.get(interact.ERROR).should( - "have.text", - "Another app with the same name already exists" - ) - }) - }) - - it("should validate application names", () => { - // App name must be letters, numbers and spaces only - // This test checks numbers and special characters specifically - const appName = "Cypress Tests" - const numberName = 12345 - const specialCharName = "£$%^" - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 }) - renameApp(appName, numberName) - cy.applicationInAppTable(numberName) - renameApp(numberName, specialCharName) - cy.get(interact.ERROR).should( - "have.text", - "App name must be letters, numbers and spaces only" - ) - // Set app name back to Cypress Tests - renameApp(numberName, appName) - }) - - const renameApp = (originalName, changedName, published, noName) => { - cy.searchForApplication(originalName) - cy.get(interact.APP_TABLE, { timeout: 1000 }).within(() => { - cy.get(".app-row-actions button") - .contains("Manage") - .eq(0) - .click({ force: true }) - }) - cy.get(".spectrum-Tabs-item").contains("Settings").click() - cy.get(".spectrum-Tabs-item.is-selected").contains("Settings") - cy.get(".settings-tab").should("be.visible") - cy.get(".details-section .page-action button") - .contains("Edit") - .click({ force: true }) - cy.updateAppName(changedName, noName) - } - }) -}) diff --git a/packages/builder/cypress/integration/revertApp.spec.js b/packages/builder/cypress/integration/revertApp.spec.js deleted file mode 100644 index 2cd806b02c..0000000000 --- a/packages/builder/cypress/integration/revertApp.spec.js +++ /dev/null @@ -1,75 +0,0 @@ -import filterTests from "../support/filterTests" -const interact = require('../support/interact') - -filterTests(['smoke', 'all'], () => { - xcontext("Revert apps", () => { - before(() => { - cy.login() - cy.createTestApp() - }) - - it("should try to revert an unpublished app", () => { - // Click revert icon - cy.get(interact.TOP_RIGHT_NAV).within(() => { - cy.get(interact.AREA_LABEL_REVERT).click({ force: true }) - }) - cy.get(interact.SPECTRUM_MODAL).within(() => { - // Enter app name before revert - cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).type("Cypress Tests") - cy.intercept('**/revert').as('revertApp') - // Click Revert - cy.get(interact.SPECTRUM_BUTTON).contains("Revert").click({ force: true }) - // Intercept Request after button click & apply assertions - cy.wait("@revertApp") - cy.get("@revertApp").its('response.body').should('have.property', 'message', "App has not yet been deployed") - cy.get("@revertApp").its('response.body').should('have.property', 'status', 400) - }) - }) - - it("should revert a published app", () => { - cy.navigateToFrontend() - - // Add initial component - Paragraph - cy.searchAndAddComponent("Paragraph") - // Publish app - cy.get(interact.SPECTRUM_BUTTON).contains("Publish").click({ force: true }) - cy.get(interact.SPECTRUM_BUTTON_GROUP).within(() => { - cy.get(interact.SPECTRUM_BUTTON).contains("Publish").click({ force: true }) - }) - cy.wait(1000) // Wait for next modal to finish loading - cy.get(interact.SPECTRUM_BUTTON_GROUP, { timeout: 1000 }).within(() => { - cy.get(interact.SPECTRUM_BUTTON).contains("Done").click({ force: true }) - }) - - // Add second component - Button - cy.searchAndAddComponent("Button") - // Click Revert - cy.get(interact.TOP_RIGHT_NAV).within(() => { - cy.get(interact.AREA_LABEL_REVERT).click({ force: true }) - }) - cy.get(interact.SPECTRUM_DIALOG_GRID).within(() => { - cy.get("input").type("Cypress Tests") - // Click Revert - cy.get(interact.SPECTRUM_BUTTON).contains("Revert").click({ force: true }) - cy.wait(2000) // Wait for app to finish reverting - }) - // Confirm Paragraph component is still visible - cy.get(interact.ROOT, { timeout: 1000 }).contains("New Paragraph") - // Confirm Button component is not visible - cy.get(interact.ROOT, { timeout: 1000 }).should("not.have.text", "New Button") - }) - - it("should enter incorrect app name when reverting", () => { - // Click Revert - cy.get(interact.TOP_RIGHT_NAV, { timeout: 1000 }).within(() => { - cy.get(interact.AREA_LABEL_REVERT).click({ force: true }) - }) - // Enter incorrect app name - cy.get(interact.SPECTRUM_DIALOG_GRID).within(() => { - cy.get("input").type("Cypress Tests") - // Revert button within modal should be disabled - cy.get(interact.SPECTRUM_BUTTON).eq(1).should('be.disabled') - }) - }) - }) -}) diff --git a/packages/builder/cypress/plugins/index.js b/packages/builder/cypress/plugins/index.js deleted file mode 100644 index 771ba886b5..0000000000 --- a/packages/builder/cypress/plugins/index.js +++ /dev/null @@ -1,23 +0,0 @@ -/// -// *********************************************************** -// This example plugins/index.js can be used to load plugins -// -// You can change the location of this file or turn off loading -// the plugins file with the 'pluginsFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/plugins-guide -// *********************************************************** - -// This function is called when a project is opened or re-opened (e.g. due to -// the project's config changing) - -/** - * @type {Cypress.PluginConfig} - */ -// eslint-disable-next-line no-unused-vars -module.exports = (on, config) => { - // `on` is used to hook into various events Cypress emits - // `config` is the resolved Cypress config - require("cypress-terminal-report/src/installLogsPrinter")(on) -} diff --git a/packages/builder/cypress/support/commands.js b/packages/builder/cypress/support/commands.js deleted file mode 100644 index 278c6504f8..0000000000 --- a/packages/builder/cypress/support/commands.js +++ /dev/null @@ -1,945 +0,0 @@ -Cypress.on("uncaught:exception", () => { - return false -}) - -// ACCOUNTS & USERS -Cypress.Commands.add("login", (email, password) => { - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 30000 }) - cy.url() - .should("include", "/builder/") - .then(url => { - if (url.includes("builder/admin")) { - // create admin user - cy.get("input").first().type("test@test.com") - cy.get('input[type="password"]').first().type("test") - cy.get('input[type="password"]').eq(1).type("test") - cy.contains("Create super admin user").click({ force: true }) - } - if (url.includes("builder/auth") || url.includes("builder/admin")) { - // login - cy.contains("Sign in to Budibase").then(() => { - if (email == null) { - cy.get("input").first().type("test@test.com") - cy.get('input[type="password"]').type("test") - } else { - cy.get("input").first().type(email) - cy.get('input[type="password"]').type(password) - } - cy.get("button").first().click({ force: true }) - cy.wait(1000) - }) - } - }) -}) - -Cypress.Commands.add("logOut", () => { - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 30000 }) - cy.get(".user-dropdown .avatar > .icon").click({ force: true }) - cy.get(".spectrum-Popover[data-cy='user-menu']").within(() => { - cy.get("li[data-cy='user-logout']").click({ force: true }) - }) - cy.wait(2000) -}) - -Cypress.Commands.add("logoutNoAppGrid", () => { - // Logs user out when app grid is not present - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 30000 }) - cy.get(".avatar > .icon").click({ force: true }) - cy.get(".spectrum-Popover[data-cy='user-menu']").within(() => { - cy.get(".spectrum-Menu-item").contains("Log out").click({ force: true }) - }) - cy.wait(2000) -}) - -Cypress.Commands.add("createUser", (email, permission) => { - cy.contains("Users").click() - cy.get(`[data-cy="add-user"]`).click() - cy.get(".spectrum-Dialog-grid").within(() => { - // Enter email - cy.get(".spectrum-Textfield-input").clear().click().type(email) - - // Select permission, if applicable - // Default is App User - if (permission != null) { - cy.get(".spectrum-Picker-label").click() - cy.get(".spectrum-Menu").within(() => { - cy.get(".spectrum-Menu-item") - .contains(permission) - .click({ force: true }) - }) - } - // Add user - cy.get(".spectrum-Button").contains("Add users").click({ force: true }) - cy.get(".spectrum-ActionButton").contains("Add email").should("not.exist") - }) - // Onboarding modal - cy.get(".spectrum-Dialog-grid", { timeout: 5000 }).contains( - "Choose your onboarding" - ) - cy.get(".spectrum-Dialog-grid").within(() => { - cy.get(".onboarding-type").eq(1).click() - cy.get(".spectrum-Button").contains("Done").click({ force: true }) - cy.get(".spectrum-Button").contains("Cancel").should("not.exist") - }) - - // Accounts created modal - Click Done button - cy.get(".spectrum-Button").contains("Done").click({ force: true }) -}) - -Cypress.Commands.add("deleteUser", email => { - // Assumes user has access to Users section - cy.contains("Users", { timeout: 2000 }).click() - cy.contains(email).click() - - cy.get(".title").within(() => { - cy.get(".spectrum-Icon").click({ force: true }) - }) - cy.get(".spectrum-Menu").within(() => { - cy.get(".spectrum-Menu-item").contains("Delete").click({ force: true }) - }) - cy.get(".spectrum-Dialog-grid").contains("Delete user").click({ force: true }) -}) - -Cypress.Commands.add("updateUserInformation", (firstName, lastName) => { - cy.get(".user-dropdown .avatar > .icon", { timeout: 2000 }).click({ - force: true, - }) - - cy.get(".spectrum-Popover[data-cy='user-menu']").within(() => { - cy.get("li[data-cy='user-info']").click({ force: true }) - }) - - cy.get(".spectrum-Modal.is-open").within(() => { - cy.get("[data-cy='user-first-name']").clear() - - if (!firstName || firstName == "") { - cy.get("[data-cy='user-first-name']").invoke("val").should("be.empty") - } else { - cy.get("[data-cy='user-first-name']") - .type(firstName) - .should("have.value", firstName) - .blur() - } - - cy.get("[data-cy='user-last-name']").clear() - - if (!lastName || lastName == "") { - cy.get("[data-cy='user-last-name']").invoke("val").should("be.empty") - } else { - cy.get("[data-cy='user-last-name']") - .type(lastName) - .should("have.value", lastName) - .blur() - } - cy.get(".confirm-wrap").within(() => { - cy.get("button").contains("Update information").click({ force: true }) - }) - cy.get(".spectrum-Dialog-grid").should("not.exist") - }) -}) - -Cypress.Commands.add("setUserRole", (user, role) => { - cy.contains("Users").click() - cy.contains(user).click() - - // Set Role - cy.wait(500) - cy.get(".spectrum-Form-itemField") - .eq(3) - .within(() => { - cy.get(".spectrum-Picker-label").click({ force: true }) - }) - cy.get(".spectrum-Menu").within(() => { - cy.get(".spectrum-Menu-itemLabel").contains(role).click({ force: true }) - }) - cy.get(".spectrum-Form-itemField").eq(3).should("contain", role) -}) - -// APPLICATIONS -Cypress.Commands.add("createTestApp", () => { - const appName = "Cypress Tests" - cy.deleteApp(appName) - cy.createApp(appName, "This app is used for Cypress testing.") -}) - -Cypress.Commands.add("createApp", (name, addDefaultTable) => { - const shouldCreateDefaultTable = - typeof addDefaultTable != "boolean" ? true : addDefaultTable - - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 30000 }) - cy.url({ timeout: 30000 }).should("include", "/apps") - cy.get(`[data-cy="create-app-btn"]`, { timeout: 5000 }).click({ force: true }) - - // If apps already exist - cy.request(`${Cypress.config().baseUrl}/api/applications?status=all`, { - timeout: 5000, - }) - .its("body") - .then(val => { - if (val.length > 0) { - cy.get(`[data-cy="create-app-btn"]`, { timeout: 5000 }).click({ - force: true, - }) - } - }) - - cy.get(".spectrum-Modal").within(() => { - cy.get("input").eq(0).should("have.focus") - if (name && name != "") { - cy.get("input").eq(0).clear() - cy.get("input").eq(0).type(name).should("have.value", name).blur() - } - cy.get(".spectrum-ButtonGroup") - .contains("Create app") - .click({ force: true }) - cy.wait(2000) - }) - if (shouldCreateDefaultTable) { - cy.createTable("Cypress Tests", true) - } -}) - -Cypress.Commands.add("deleteApp", name => { - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 30000 }) - cy.wait(2000) - cy.request(`${Cypress.config().baseUrl}/api/applications?status=all`) - .its("body") - .then(val => { - const findAppName = val.some(val => val.name == name) - if (findAppName) { - if (val.length > 0) { - const appId = val.reduce((acc, app) => { - if (name === app.name) { - acc = app.appId - } - return acc - }, "") - - if (appId == "") { - return - } - - // Go to app overview - const appIdParsed = appId.split("_").pop() - const actionEleId = `[data-cy=row_actions_${appIdParsed}]` - cy.get(actionEleId).within(() => { - cy.contains("Manage").click({ force: true }) - }) - cy.wait(500) - - // Unpublish first if needed - cy.get(`[data-cy="app-status"]`).then($status => { - if ($status.text().includes("- Unpublish")) { - // Exact match for Unpublish - cy.contains("Unpublish").click({ force: true }) - cy.get(".spectrum-Modal").within(() => { - cy.contains("Unpublish app").click({ force: true }) - }) - } - }) - - // Delete app - cy.get(".app-overview-actions-icon").within(() => { - cy.get(".spectrum-Icon").click({ force: true }) - }) - cy.get(".spectrum-Menu").contains("Delete").click({ force: true }) - cy.get(".spectrum-Dialog-grid").within(() => { - cy.get("input").type(name) - }) - cy.get(".spectrum-Button--warning").click() - } else { - return - } - } else { - return - } - }) -}) - -Cypress.Commands.add("deleteAllApps", () => { - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 30000 }) - cy.wait(500) - cy.request(`${Cypress.config().baseUrl}/api/applications?status=all`, { - timeout: 5000, - }) - .its("body") - .then(val => { - for (let i = 0; i < val.length; i++) { - cy.deleteApp(val[i].name) - cy.reload() - } - }) -}) - -Cypress.Commands.add("unlockApp", unlock_config => { - let config = { ...unlock_config } - - cy.get(".spectrum-Modal .spectrum-Dialog[data-cy='app-lock-modal']") - .should("be.visible") - .within(() => { - if (config.owned) { - cy.get(".spectrum-Dialog-heading").contains("Locked by you") - cy.get(".lock-expiry-body").contains( - "This lock will expire in 10 minutes from now" - ) - - cy.intercept("**/lock").as("unlockApp") - cy.get(".spectrum-Button") - .contains("Release Lock") - .click({ force: true }) - cy.wait("@unlockApp") - cy.get("@unlockApp").its("response.statusCode").should("eq", 200) - cy.get("@unlockApp").its("response.body").should("deep.equal", { - message: "Lock released successfully.", - }) - } else { - //Show the name ? - cy.get(".lock-expiry-body").should("not.be.visible") - cy.get(".spectrum-Button").contains("Done") - } - }) -}) - -Cypress.Commands.add("updateAppName", (changedName, noName) => { - cy.get(".spectrum-Modal").within(() => { - if (noName == true) { - cy.get("input").clear() - cy.get(".spectrum-Dialog-grid") - .click() - .contains("App name must be letters, numbers and spaces only") - return cy - } - cy.get("input").clear() - cy.get("input") - .eq(0) - .type(changedName) - .should("have.value", changedName) - .blur() - cy.get(".spectrum-ButtonGroup").contains("Save").click({ force: true }) - cy.wait(500) - }) -}) - -Cypress.Commands.add("publishApp", resolvedAppPath => { - // Assumes you have navigated to an application first - cy.get(".toprightnav button.spectrum-Button") - .contains("Publish") - .click({ force: true }) - - cy.get(".spectrum-Modal [data-cy='deploy-app-modal']") - .should("be.visible") - .within(() => { - cy.get(".spectrum-Button").contains("Publish").click({ force: true }) - cy.wait(1000) - }) - - // Verify that the app url is presented correctly to the user - cy.get(".spectrum-Modal [data-cy='deploy-app-success-modal']") - .should("be.visible") - .within(() => { - let appUrl = Cypress.config().baseUrl + "/app/" + resolvedAppPath - cy.get("[data-cy='deployed-app-url'] input").should("have.value", appUrl) - cy.get(".spectrum-Button").contains("Done").click({ force: true }) - }) -}) - -Cypress.Commands.add("alterAppVersion", (appId, version) => { - return cy - .request("put", `${Cypress.config().baseUrl}/api/applications/${appId}`, { - version: version || "0.0.1-alpha.0", - }) - .then(resp => { - expect(resp.status).to.eq(200) - }) -}) - -Cypress.Commands.add("importApp", (exportFilePath, name) => { - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 30000 }) - - cy.request(`${Cypress.config().baseUrl}/api/applications?status=all`) - .its("body") - .then(val => { - if (val.length > 0) { - cy.get(`[data-cy="create-app-btn"]`).click({ force: true }) - } - cy.wait(500) - cy.get(`[data-cy="import-app-btn"]`).click({ - force: true, - }) - }) - - cy.get(".spectrum-Modal").within(() => { - cy.get("input").eq(1).should("have.focus") - - cy.get(".spectrum-Dropzone").selectFile(exportFilePath, { - action: "drag-drop", - }) - - cy.get(".gallery .filename").contains("exported-app.txt") - - if (name && name != "") { - cy.get("input").eq(0).type(name).should("have.value", name).blur() - } - cy.get(".confirm-wrap button") - .should("not.be.disabled") - .click({ force: true }) - cy.wait(3000) - }) -}) - -// Filters visible with 1 or more -Cypress.Commands.add("searchForApplication", appName => { - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 30000 }) - cy.wait(2000) - - // No app filter functionality if only 1 app exists - cy.request(`${Cypress.config().baseUrl}/api/applications?status=all`) - .its("body") - .then(val => { - if (val.length < 2) { - return - } else { - // Searches for the app - cy.get(".filter").then(() => { - cy.get(".spectrum-Textfield").within(() => { - cy.get("input").eq(0).clear({ force: true }) - cy.get("input").eq(0).type(appName, { force: true }) - }) - }) - } - }) -}) - -// Assumes there are no others -Cypress.Commands.add("applicationInAppTable", appName => { - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 30000 }) - cy.get(".appTable", { timeout: 5000 }).within(() => { - cy.get(".title").contains(appName).should("exist") - }) -}) - -Cypress.Commands.add("createAppFromScratch", appName => { - cy.get(`[data-cy="create-app-btn"]`) - .contains("Start from scratch") - .click({ force: true }) - cy.get(".spectrum-Modal").within(() => { - cy.get("input") - .eq(0) - .clear() - .type(appName) - .should("have.value", appName) - .blur() - cy.get(".spectrum-ButtonGroup").contains("Create app").click() - cy.wait(10000) - }) - cy.createTable("Cypress Tests", true) -}) - -// TABLES -Cypress.Commands.add("createTable", (tableName, initialTable) => { - // Creates an internal Budibase DB table - if (!initialTable) { - cy.navigateToDataSection() - } - cy.get(`[data-cy="new-datasource"]`, { timeout: 2000 }).click() - cy.wait(2000) - cy.get(".item", { timeout: 2000 }) - .contains("Budibase DB") - .click({ force: true }) - .then(() => { - cy.get(".spectrum-Button", { timeout: 2000 }) - .contains("Continue") - .click({ force: true }) - }) - cy.get(".spectrum-Modal").contains("Create Table", { timeout: 10000 }) - cy.get(".spectrum-Modal", { timeout: 2000 }).within(() => { - cy.get("input", { timeout: 2000 }).first().type(tableName).blur() - cy.get(".spectrum-ButtonGroup").contains("Create").click() - }) - // Ensure modal has closed and table is created - cy.get(".spectrum-Modal", { timeout: 2000 }).should("not.exist") - cy.get(".nav-item", { timeout: 2000 }) - .contains("Budibase DB") - .click({ force: true }) - cy.get(".spectrum-Tabs-content", { timeout: 2000 }).should( - "contain", - tableName - ) -}) - -Cypress.Commands.add("createTestTableWithData", () => { - cy.createTable("dog") - cy.addColumn("dog", "name", "Text") - cy.addColumn("dog", "age", "Number") -}) - -Cypress.Commands.add( - "addColumn", - (tableName, columnName, type, multiOptions = null) => { - // Select Table - cy.selectTable(tableName) - cy.contains(".nav-item", tableName).click() - cy.contains("Create column").click() - - // Configure column - cy.get(".spectrum-Modal").within(() => { - cy.get("input").first().type(columnName).blur() - - // Unset table display column - cy.contains("display column").click({ force: true }) - cy.get(".spectrum-Picker-label").click() - cy.contains(type).click() - - // Add options for Multi-select Type - if (multiOptions !== null) { - cy.get(".spectrum-Textfield-input").eq(1).type(multiOptions) - } - - cy.contains("Save Column").click() - }) - } -) - -Cypress.Commands.add("addRow", values => { - cy.contains("Create row").click() - cy.get(".spectrum-Modal").within(() => { - for (let i = 0; i < values.length; i++) { - cy.get("input").eq(i).type(values[i]).blur() - } - cy.get(".spectrum-ButtonGroup").contains("Create").click() - }) -}) - -Cypress.Commands.add("addRowMultiValue", values => { - cy.contains("Create row").click() - cy.get(".spectrum-Modal").within(() => { - cy.get(".spectrum-Form-itemField") - .click() - .then(() => { - cy.get(".spectrum-Popover").within(() => { - for (let i = 0; i < values.length; i++) { - cy.get(".spectrum-Menu-item").eq(i).click() - } - }) - cy.get(".spectrum-Dialog-grid").click("top") - cy.get(".spectrum-ButtonGroup").contains("Create").click() - }) - }) -}) - -Cypress.Commands.add("selectTable", tableName => { - cy.get(".nav-item").contains("Budibase DB").click() - cy.contains(".nav-item", tableName).click() -}) - -Cypress.Commands.add("addCustomSourceOptions", totalOptions => { - cy.get('[data-cy="customOptions-prop-control"]').within(() => { - cy.get(".spectrum-ActionButton-label").click({ force: true }) - }) - for (let i = 0; i < totalOptions; i++) { - // Add radio button options - cy.get(".spectrum-Button-label", { timeout: 1000 }) - .contains("Add Option") - .click({ force: true }) - .then(() => { - cy.get("[placeholder='Label']", { timeout: 500 }).eq(i).type(i) - cy.get("[placeholder='Value']").eq(i).type(i) - }) - } - // Save options - cy.get(".spectrum-Button").contains("Save").click({ force: true }) -}) - -// DESIGN SECTION -Cypress.Commands.add("searchAndAddComponent", component => { - // Open component menu - cy.get(".icon-side-nav").within(() => { - cy.get(".icon-side-nav-item").eq(1).click() - }) - cy.get(".add-component > .spectrum-Button") - .contains("Add component") - .click({ force: true }) - cy.get(".container", { timeout: 1000 }).within(() => { - cy.get(".title").should("contain", "Add component") - - // Search and add component - cy.get(".spectrum-Textfield-input").clear().type(component) - cy.get(".body").within(() => { - cy.get(".component") - .contains(new RegExp("^" + component + "$"), { timeout: 3000 }) - .click({ force: true }) - }) - }) - cy.wait(1000) - cy.location().then(loc => { - const params = loc.pathname.split("/") - const componentId = params[params.length - 1] - cy.getComponent(componentId, { timeout: 3000 }).should("exist") - return cy.wrap(componentId) - }) -}) - -Cypress.Commands.add("deleteComponentByName", componentName => { - cy.get(".body") - .eq(0) - .contains(componentName) - .siblings(".actions") - .within(() => { - cy.get(".spectrum-Icon").click({ force: true }) - }) - cy.get(".spectrum-Menu").contains("Delete").click() - cy.get(".spectrum-Dialog").contains("Delete Component").click() -}) - -Cypress.Commands.add("addComponent", (category, component) => { - if (category) { - cy.get(`[data-cy="category-${category}"]`, { timeout: 3000 }).click({ - force: true, - }) - } - cy.wait(500) - if (component) { - cy.get(`[data-cy="component-${component}"]`, { timeout: 3000 }).click({ - force: true, - }) - } - cy.wait(1000) - cy.location().then(loc => { - const params = loc.pathname.split("/") - const componentId = params[params.length - 1] - cy.getComponent(componentId, { timeout: 3000 }).should("exist") - return cy.wrap(componentId) - }) -}) - -Cypress.Commands.add("getComponent", componentId => { - return cy - .get("iframe") - .its("0.contentDocument") - .should("exist") - .its("body") - .should("not.be.undefined") - .then(cy.wrap) - .find(`[data-id='${componentId}']`) -}) - -Cypress.Commands.add("createScreen", (route, accessLevelLabel) => { - // Blank Screen - cy.contains("Design").click() - cy.get(".spectrum-Button").contains("Add screen").click({ force: true }) - cy.get(".spectrum-Modal").within(() => { - cy.get("[data-cy='blank-screen']").click() - cy.get(".spectrum-Button").contains("Continue").click({ force: true }) - }) - cy.wait(500) - cy.get(".spectrum-Dialog-grid", { timeout: 500 }).within(() => { - cy.get(".spectrum-Form-itemField").eq(0).type(route) - cy.get(".confirm-wrap").contains("Continue").click({ force: true }) - }) - - cy.get(".spectrum-Modal", { timeout: 1000 }).within(() => { - if (accessLevelLabel) { - cy.get(".spectrum-Picker-label").click() - cy.wait(500) - cy.contains(accessLevelLabel).click() - } - cy.get(".spectrum-Button").contains("Done").click({ force: true }) - }) -}) - -Cypress.Commands.add( - "createDatasourceScreen", - (datasourceNames, accessLevelLabel) => { - cy.contains("Design").click() - cy.get(".spectrum-Button").contains("Add screen").click({ force: true }) - cy.get(".spectrum-Dialog-grid").within(() => { - cy.get("[data-cy='autogenerated-screens']").click() - cy.intercept("**/api/datasources").as("autoScreens") - cy.get(".spectrum-Button").contains("Continue").click({ force: true }) - cy.wait("@autoScreens") - cy.wait(5000) - }) - cy.get("[data-cy='autogenerated-screens']").should("not.exist") - cy.get("[data-cy='data-source-modal']", { timeout: 10000 }).within(() => { - for (let i = 0; i < datasourceNames.length; i++) { - cy.get(".data-source-entry") - .contains(datasourceNames[i], { timeout: 20000 }) - .click({ force: true }) - // Ensure the check mark is visible - cy.get(".data-source-entry") - .contains(datasourceNames[i]) - .get(".data-source-check", { timeout: 20000 }) - .should("exist") - } - - cy.get(".spectrum-Button").contains("Confirm").click({ force: true }) - }) - - cy.get(".spectrum-Modal", { timeout: 10000 }).within(() => { - if (accessLevelLabel) { - cy.get(".spectrum-Picker-label", { timeout: 10000 }).click() - cy.contains(accessLevelLabel).click() - } - cy.get(".spectrum-Button").contains("Done").click({ force: true }) - }) - - cy.contains("Design").click() - } -) - -Cypress.Commands.add( - "createAutogeneratedScreens", - (screenNames, accessLevelLabel) => { - cy.navigateToAutogeneratedModal() - - for (let i = 0; i < screenNames.length; i++) { - cy.get(".data-source-entry").contains(screenNames[i]).click() - } - - cy.get(".spectrum-Modal").within(() => { - if (accessLevelLabel) { - cy.get(".spectrum-Picker-label").click() - cy.wait(500) - cy.contains(accessLevelLabel).click() - } - cy.get(".spectrum-Button").contains("Confirm").click({ force: true }) - cy.wait(4000) - }) - } -) - -Cypress.Commands.add("filterScreensAccessLevel", accessLevel => { - // Filters screens by access level dropdown - cy.get(".body").within(() => { - cy.get(".spectrum-Form-item").eq(1).click() - }) - cy.get(".spectrum-Menu").within(() => { - cy.contains(accessLevel).click() - }) -}) - -Cypress.Commands.add("deleteScreen", screen => { - // Navigates to Design section and deletes specified screen - cy.contains("Design").click() - cy.get(".body").within(() => { - cy.contains(screen) - .siblings(".actions") - .within(() => { - cy.get(".spectrum-Icon").click({ force: true }) - }) - }) - cy.get(".spectrum-Menu > .spectrum-Menu-item > .spectrum-Menu-itemLabel") - .contains("Delete") - .click() - - cy.get( - ".spectrum-Dialog-grid > .spectrum-ButtonGroup > .confirm-wrap > .spectrum-Button" - ).click({ force: true }) - cy.get(".spectrum-Dialog-grid", { timeout: 10000 }).should("not.exist") -}) - -Cypress.Commands.add("deleteAllScreens", () => { - // Deletes all screens - cy.get(".body") - .find(".nav-item") - .its("length") - .then(len => { - for (let i = 0; i < len; i++) { - cy.get(".body > .nav-item") - .eq(0) - .invoke("text") - .then(text => { - cy.deleteScreen(text.trim()) - }) - } - }) -}) - -// NAVIGATION -Cypress.Commands.add("navigateToFrontend", () => { - // Clicks on Design tab and then the Home nav item - cy.wait(500) - cy.intercept("**/preview").as("preview") - cy.contains("Design").click() - cy.wait("@preview") - cy.get("@preview").then(res => { - if (res.statusCode != 200) { - cy.reload() - } - }) - cy.get(".spectrum-Search", { timeout: 20000 }).type("/") - cy.get(".nav-item", { timeout: 2000 }).contains("home").click({ force: true }) -}) - -Cypress.Commands.add("navigateToDataSection", () => { - // Clicks on the Data tab - cy.wait(500) - cy.contains("Data").click() -}) - -Cypress.Commands.add("navigateToAutogeneratedModal", () => { - // Screen name must already exist within datasource - cy.contains("Design").click() - cy.get(".spectrum-Button").contains("Add screen").click({ force: true }) - cy.get(".spectrum-Modal").within(() => { - cy.get(".item", { timeout: 2000 }) - .contains("Autogenerated screens") - .click({ force: true }) - cy.get(".spectrum-Button").contains("Continue").click({ force: true }) - cy.wait(500) - }) -}) - -// DATASOURCES -Cypress.Commands.add("selectExternalDatasource", datasourceName => { - // Navigates to Data Section - cy.navigateToDataSection() - // Open Datasource modal - cy.get(".nav").within(() => { - cy.get("[data-cy='new-datasource']").click() - }) - // Clicks specified datasource & continue - cy.get(".item-list", { timeout: 1000 }).contains(datasourceName).click() - cy.get(".spectrum-Dialog-grid").within(() => { - cy.get(".spectrum-Button").contains("Continue").click({ force: true }) - }) - cy.wait(500) -}) - -Cypress.Commands.add("addDatasourceConfig", (datasource, skipFetch) => { - // selectExternalDatasource should be called prior to this - // Adds the config for specified datasource & fetches tables - // Currently supports MySQL, PostgreSQL, Oracle - // Host IP Address - cy.get(".spectrum-Dialog-grid", { timeout: 500 }).within(() => { - cy.get(".form-row") - .eq(0) - .within(() => { - cy.get(".spectrum-Textfield").within(() => { - if (datasource == "Oracle") { - cy.get("input").clear().type(Cypress.env("oracle").HOST) - } else { - cy.get("input") - .clear({ force: true }) - .type(Cypress.env("HOST_IP"), { force: true }) - } - }) - }) - }) - // Database Name - cy.get(".spectrum-Dialog-grid").within(() => { - if (datasource == "MySQL") { - cy.get(".form-row") - .eq(4) - .within(() => { - cy.get("input").clear().type(Cypress.env("mysql").DATABASE) - }) - } else { - cy.get(".form-row") - .eq(2) - .within(() => { - if (datasource == "PostgreSQL") { - cy.get("input").clear().type(Cypress.env("postgresql").DATABASE) - } - if (datasource == "Oracle") { - cy.get("input").clear().type(Cypress.env("oracle").DATABASE) - } - }) - } - }) - // User - cy.get(".spectrum-Dialog-grid").within(() => { - if (datasource == "MySQL") { - cy.get(".form-row") - .eq(2) - .within(() => { - cy.get("input").clear().type(Cypress.env("mysql").USER) - }) - } else { - cy.get(".form-row") - .eq(3) - .within(() => { - if (datasource == "PostgreSQL") { - cy.get("input").clear().type(Cypress.env("postgresql").USER) - } - if (datasource == "Oracle") { - cy.get("input").clear().type(Cypress.env("oracle").USER) - } - }) - } - }) - // Password - cy.get(".spectrum-Dialog-grid").within(() => { - if (datasource == "MySQL") { - cy.get(".form-row") - .eq(3) - .within(() => { - cy.get("input").clear().type(Cypress.env("mysql").PASSWORD) - }) - } else { - cy.get(".form-row") - .eq(4) - .within(() => { - if (datasource == "PostgreSQL") { - cy.get("input").clear().type(Cypress.env("postgresql").PASSWORD) - } - if (datasource == "Oracle") { - cy.get("input").clear().type(Cypress.env("oracle").PASSWORD) - } - }) - } - }) - // Click to fetch tables - if (skipFetch) { - cy.get(".spectrum-Dialog-grid").within(() => { - cy.get(".spectrum-Button") - .contains("Skip table fetch") - .click({ force: true }) - }) - } else { - cy.intercept("**/tables").as("datasourceTables") - cy.get(".spectrum-Dialog-grid").within(() => { - cy.get(".spectrum-Button") - .contains("Save and fetch tables") - .click({ force: true }) - }) - // Wait for tables to be fetched - cy.wait("@datasourceTables", { timeout: 60000 }) - } -}) - -Cypress.Commands.add("createRestQuery", (method, restUrl, queryPrettyName) => { - // addExternalDatasource should be called prior to this - // Configures REST datasource & sends query - cy.get(".spectrum-Button", { timeout: 1000 }) - .contains("Add query") - .click({ force: true }) - // Select Method & add Rest URL - cy.get(".spectrum-Picker-label").eq(1).click() - cy.get(".spectrum-Menu").contains(method).click() - cy.get("input").clear().type(restUrl) - // Send query - cy.get(".spectrum-Button").contains("Send").click({ force: true }) - cy.get(".spectrum-Button", { timeout: 500 }) - .contains("Save") - .click({ force: true }) - cy.get(".hierarchy-items-container") - .should("contain", method) - .and("contain", queryPrettyName) -}) - -// MISC -Cypress.Commands.add("closeModal", () => { - cy.get(".spectrum-Modal", { timeout: 2000 }).within(() => { - cy.get(".close-icon").click() - }) - // Confirm modal has closed - cy.get(".spectrum-Modal", { timeout: 10000 }).should("not.exist") -}) - -Cypress.Commands.add("expandBudibaseConnection", () => { - if (Cypress.$(".nav-item > .content > .opened").length === 0) { - // expand the Budibase DB connection string - cy.get(".icon.arrow").eq(0).click() - } -}) diff --git a/packages/builder/cypress/support/cookies.js b/packages/builder/cypress/support/cookies.js deleted file mode 100644 index 3e2fba6481..0000000000 --- a/packages/builder/cypress/support/cookies.js +++ /dev/null @@ -1,3 +0,0 @@ -Cypress.Cookies.defaults({ - preserve: "budibase:auth", -}) diff --git a/packages/builder/cypress/support/filterTests.js b/packages/builder/cypress/support/filterTests.js deleted file mode 100644 index 074fd05d33..0000000000 --- a/packages/builder/cypress/support/filterTests.js +++ /dev/null @@ -1,16 +0,0 @@ -const filterTests = (testTags, runTest) => { - // testTags is an array of tags - // runTest is all tests - if (Cypress.env("TEST_TAGS")) { - const tags = Cypress.env("TEST_TAGS").split("/") - const found = testTags.some($testTags => tags.includes($testTags)) - - if (found) { - runTest() - } - } else { - runTest() - } -} - -export default filterTests diff --git a/packages/builder/cypress/support/index.js b/packages/builder/cypress/support/index.js deleted file mode 100644 index acd53a1592..0000000000 --- a/packages/builder/cypress/support/index.js +++ /dev/null @@ -1,22 +0,0 @@ -// *********************************************************** -// This example support/index.js is processed and -// loaded automatically before your test files. -// -// This is a great place to put global configuration and -// behavior that modifies Cypress. -// -// You can change the location of this file or turn off -// automatically serving support files with the -// 'supportFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/configuration -// *********************************************************** - -// Import commands.js using ES2015 syntax: -import "./commands" -import "./cookies" - -// Alternatively you can use CommonJS syntax: -// require('./commands') -require("cypress-terminal-report/src/installLogsCollector")() diff --git a/packages/builder/cypress/support/interact.js b/packages/builder/cypress/support/interact.js deleted file mode 100644 index 4f2451ce4b..0000000000 --- a/packages/builder/cypress/support/interact.js +++ /dev/null @@ -1,136 +0,0 @@ -// createApp test -export const CREATE_APP_BUTTON = '[data-cy="create-app-btn"]' -export const TEMPLATE_CATEGORY_FILTER = ".template-category-filters" -export const TEMPLATE_CATEGORY = ".template-categories" -export const APP_TABLE = ".appTable" -export const SPECTRUM_BUTTON_TEMPLATE = ".spectrum-Button" -export const TEMPLATE_CATEGORY_ACTIONGROUP = ".template-category" -export const TEMPLATE_CATEGORY_FILTER_ACTIONBUTTON = - ".template-category-filters .spectrum-ActionButton" -export const SPECTRUM_MODAL = ".spectrum-Modal" -export const APP_NAME_INPUT = "input" // we need to update this with atribute cy-data; -export const SPECTRUM_BUTTON_GROUP = ".spectrum-ButtonGroup" -export const SPECTRUM_MODAL_INPUT = ".spectrum-Modal input" - -//AddMultiOptionDatatype -export const CATEGORY_DATA = '[data-cy="category-Data"]' -export const COMPONENT_DATA_PROVIDER = '[data-cy="component-Data Provider"]' -export const DATASOURCE_PROP_CONTROL = '[data-cy="dataSource-prop-control"]' -export const DROPDOWN = ".dropdown" -export const SPECTRUM_PICKER_LABEL = ".spectrum-Picker-label" -export const DATASOURCE_FIELD_CONTROL = '[data-cy="field-prop-control"]' -export const OPTION_TYPE_PROP_CONTROL = '[data-cy="optionsType-prop-control' - -//AddRadioButtons -export const SPECTRUM_POPOVER = ".spectrum-Popover" -export const OPTION_SOURCE_PROP_CONROL = '[data-cy="optionsSource-prop-control' -export const APP_TABLE_STATUS = ".appTable .app-status" -export const APP_TABLE_ROW_ACTION = ".appTable .app-row-actions" -export const APP_TABLE_APP_NAME = '[data-cy="app-name-link"]' -export const DEPLOYMENT_TOP_NAV_GLOBESTRIKE = - ".deployment-top-nav svg[aria-label=GlobeStrike]" -export const DEPLOYMENT_TOP_GLOBE = ".deployment-top-nav svg[aria-label=Globe]" -export const PUBLISH_POPOVER_MENU = '[data-cy="publish-popover-menu"]' -export const PUBLISH_POPOVER_ACTION = '[data-cy="publish-popover-action"]' -export const PUBLISH_POPOVER_MESSAGE = ".publish-popover-message" -export const SPECTRUM_BUTTON = ".spectrum-Button" -export const SPECTRUM_LINK = ".spectrum-Link" -export const TOPRIGHTNAV_BUTTON_SPECTRUM = ".toprightnav button.spectrum-Button" - -//createComponents -export const SETTINGS = "[data-cy=Settings]" -export const SETTINGS_INPUT = "[data-cy=setting-text] input" -export const DESIGN = "[data-cy=Design]" -export const FONT_SIZE_PROP_CONTROL = "[data-cy=font-size-prop-control]" -export const DATA_CY_DATASOURCE = "[data-cy=setting-dataSource]" -export const DROPDOWN_CONTAINER = ".dropdown-container" -export const SPECTRUM_PICKER = ".spectrum-Picker" - -//autoScreens -export const LABEL_ADD_CIRCLE = "[aria-label=AddCircle]" -export const ITEM_DISABLED = ".item.disabled" -export const CONFIRM_WRAP_SPE_BUTTON = ".confirm-wrap .spectrum-Button" -export const DATA_SOURCE_ENTRY = ".data-source-entry" -export const BODY = ".body" - -//publishWorkFlow -export const DEPLOY_APP_MODAL = ".spectrum-Modal [data-cy=deploy-app-modal]" -export const DEPLOY_SUCCESS_MODAL = - ".spectrum-Modal [data-cy=deploy-app-success-modal]" -export const DEPLOY_APP_URL_INPUT = "[data-cy=deployed-app-url] input" -export const GLOBESTRIKE = "svg[aria-label=GlobeStrike]" -export const GLOBE = "svg[aria-label=Globe]" -export const UNPUBLISH_MODAL = "[data-cy=unpublish-modal]" -export const CONFIRM_WRAP_BUTTON = ".confirm-wrap button" -export const DEPLOYMENT_TOP_NAV = ".deployment-top-nav" - -//changeAppiconAndColour -export const APP_ROW_ACTION = ".app-row-actions-icon" -export const SPECTRUM_MENU = ".spectrum-Menu" -export const ICON_ITEM = ".icon-item" -export const FILL = ".fill" -export const COLOURSS = ".colors" -export const AREA_LABEL = "[aria-label]" -export const TITLE = ".title" -export const GRID = ".grid" -export const COLOUR = ".color" - -//createAutomation -export const ADD_BUTTON_SPECTRUM = ".add-button .spectrum-Icon" -export const MODAL_INNER_WRAPPER = ".modal-inner-wrapper" -export const SPECTRUM_BUTTON_CTA = ".spectrum-Button--cta" -export const SPECTRUM_TEXTFIELD_INPUT = ".spectrum-Textfield-input" - -//createTable -export const TABLE_TITLE_H1 = ".table-title h1" -export const TABLE_TITLE = ".title" -export const SPECTRUM_TABLE_EDIT = ".spectrum-Table-editIcon > use" -export const SPECTRUM_SWITCH_INPUT = ".spectrum-Switch-input" -export const SPECTRUM_CHECKBOX_INPUT = ".spectrum-Checkbox-input" -export const SPECTRUM_PAGINATION = ".spectrum-Pagination" -export const SPECTRUM_ACTION_BUTTON = ".spectrum-ActionButton" -export const SPECTRUM_BODY_SECOND = ".spectrum-Body--secondary" -export const POPOVERS = ".popovers" -export const SPECTRUM_DIALOG_GRID = ".spectrum-Dialog-grid" -export const DELETE_COLUMN_CONFIRM = '[data-cy="delete-column-confirm"]' -export const NAV_ITEM = ".nav-item" -export const ACTION_SPECTRUM_ICON = ".actions .spectrum-Icon" -export const SPECTRUM_MENU_CHILD2 = ".spectrum-Menu > :nth-child(2)" -export const DELETE_TABLE_CONFIRM = '[data-cy="delete-table-confirm"]' - -//adminAndManagement Folder -export const SPECTRUM_TABLE = ".spectrum-Table" -export const SPECTRUM_SIDENAV = ".spectrum-SideNav" -export const SPECTRUM_TABLE_ROW = ".spectrum-Table-row" -export const SPECTRUM_TABLE_CELL = ".spectrum-Table-cell" -export const FIELD = ".field" -export const CONTAINER = ".container" -export const REGENERATE = ".regenerate" -export const SPECTRUM_DIALOG_CONTENT = ".spectrum-Dialog-content" -export const SPECTRUM_ICON = ".spectrum-Icon" -export const SPECTRUM_HEADING = ".spectrum-Heading" -export const SPECTRUM_FORM_ITEMFIELD = ".spectrum-Form-itemField" -export const LIST_ITEMS = ".list-items" - -//createView -export const SPECTRUM_MENU_ITEM_LABEL = ".spectrum-Menu-itemLabel" - -//revertApp -export const TOP_RIGHT_NAV = ".toprightnav" -export const AREA_LABEL_REVERT = "[aria-label=Revert]" -export const ROOT = ".root" - -//queryLevelTransformers -export const SPECTRUM_TABS_ITEM = ".spectrum-Tabs-itemLabel" -export const CODEMIRROR_TEXTAREA = ".CodeMirror textarea" - -//renameApplication -export const WRAPPER = ".wrapper" -export const ERROR = ".error" -export const AREA_LABEL_MORE = "[aria-label=More]" -export const APP_ROW_ACTION_MENU_POPOVER = - '[data-cy="app-row-actions-menu-popover"]' -export const SPECTRUM_MENU_ITEM = ".spectrum-Menu-item" - -//commands -export const HOME_LOGO = ".home-logo" diff --git a/packages/builder/cypress/support/queryLevelTransformerFunction.js b/packages/builder/cypress/support/queryLevelTransformerFunction.js deleted file mode 100644 index 7dc05018f8..0000000000 --- a/packages/builder/cypress/support/queryLevelTransformerFunction.js +++ /dev/null @@ -1,14 +0,0 @@ -/* eslint-disable */ -const breweries = data -const totals = {} - -for (let brewery of breweries) - {const state = brewery.state - if (totals[state] == null) - {totals[state] = 1 - } else - {totals[state]++ - } -} -const entries = Object.entries(totals) -return entries.map(([state, count]) => ({ state, count })) diff --git a/packages/builder/cypress/support/queryLevelTransformerFunctionWithData.js b/packages/builder/cypress/support/queryLevelTransformerFunctionWithData.js deleted file mode 100644 index fcf50b4412..0000000000 --- a/packages/builder/cypress/support/queryLevelTransformerFunctionWithData.js +++ /dev/null @@ -1,31 +0,0 @@ -/* eslint-disable */ -const breweries = data -const totals = {} -for (let brewery of breweries) - {const state = brewery.state - if (totals[state] == null) - {totals[state] = 1 - } else - {totals[state]++ - } -} -const stateCodes = - {texas: "tx", - colorado: "co", - florida: "fl", - iwoa: "ia", - louisiana: "la", - california: "ca", - pennsylvania: "pa", - georgia: "ga", - "new hampshire": "nh", - virginia: "va", - michigan: "mi", - maryland: "md", - ohio: "oh", -} -const entries = Object.entries(totals) -return entries.map(([state, count]) => - {stateCodes[state.toLowerCase()] - return { state, count, flag: "http://flags.ox3.in/svg/us/${stateCode}.svg" } -}) diff --git a/packages/builder/cypress/ts/setup.ts b/packages/builder/cypress/ts/setup.ts deleted file mode 100644 index b6b12bf730..0000000000 --- a/packages/builder/cypress/ts/setup.ts +++ /dev/null @@ -1,4 +0,0 @@ -// @ts-ignore -import { run } from "../setup" - -run("../../server/src/index", "../../worker/src/index") diff --git a/packages/builder/package.json b/packages/builder/package.json index 27647f4da2..92dabe7212 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/builder", - "version": "2.2.26", + "version": "2.2.27-alpha.0", "license": "GPL-3.0", "private": true, "scripts": { @@ -9,20 +9,7 @@ "dev:builder": "routify -c dev:vite", "dev:vite": "vite --host 0.0.0.0", "rollup": "rollup -c -w", - "test": "jest", - "cy:setup": "ts-node ./cypress/ts/setup.ts", - "cy:setup:ci": "node ./cypress/setup.js", - "cy:open": "cypress open", - "cy:run": "cypress run", - "cy:run:ci": "cypress run --headed --browser chrome --spec cypress/integration/createApp.spec.js", - "cy:run:ci:record": "xvfb-run cypress run --headed --browser chrome --record", - "cy:test": "start-server-and-test cy:setup http://localhost:4100/builder cy:run", - "cy:ci": "start-server-and-test cy:setup:ci http://localhost:4100/builder cy:run:ci", - "cy:ci:record": "start-server-and-test cy:setup:ci http://localhost:4100/builder cy:run:ci:record; npm run cy:ci:report", - "cy:ci:report": "mochawesome-merge cypress/reports/*.json > cypress/reports/testReport.json && marge cypress/reports/testReport.json --reportDir cypress/reports --inline", - "cy:ci:notify": "node scripts/cypressResultsWebhook", - "cy:debug": "start-server-and-test cy:setup http://localhost:4100/builder cy:open", - "cy:debug:ci": "start-server-and-test cy:setup:ci http://localhost:4100/builder cy:open" + "test": "jest" }, "jest": { "globals": { @@ -71,11 +58,15 @@ } }, "dependencies": { - "@budibase/bbui": "^2.2.26", - "@budibase/client": "^2.2.26", - "@budibase/frontend-core": "^2.2.26", - "@budibase/string-templates": "^2.2.26", + "@budibase/bbui": "2.2.27-alpha.0", + "@budibase/client": "2.2.27-alpha.0", + "@budibase/frontend-core": "2.2.27-alpha.0", + "@budibase/string-templates": "2.2.27-alpha.0", + "@fortawesome/fontawesome-svg-core": "^6.2.1", + "@fortawesome/free-brands-svg-icons": "^6.2.1", + "@fortawesome/free-solid-svg-icons": "^6.2.1", "@sentry/browser": "5.19.1", + "@spectrum-css/accordion": "^3.0.24", "@spectrum-css/page": "^3.0.1", "@spectrum-css/vars": "^3.0.1", "codemirror": "^5.59.0", @@ -87,7 +78,7 @@ "shortid": "2.2.15", "svelte-dnd-action": "^0.9.8", "svelte-loading-spinners": "^0.1.1", - "svelte-portal": "0.1.0", + "svelte-portal": "1.0.0", "uuid": "8.3.1", "yup": "0.29.2" }, diff --git a/packages/builder/cypress/setup.js b/packages/builder/setup.js similarity index 79% rename from packages/builder/cypress/setup.js rename to packages/builder/setup.js index 0e2f25b028..744c20896a 100644 --- a/packages/builder/cypress/setup.js +++ b/packages/builder/setup.js @@ -1,14 +1,14 @@ -const cypressConfig = require("../cypress.json") +const testConfig = require("./testConfig.json") // normal development system -const SERVER_PORT = cypressConfig.env.PORT -const WORKER_PORT = cypressConfig.env.WORKER_PORT +const SERVER_PORT = testConfig.env.PORT +const WORKER_PORT = testConfig.env.WORKER_PORT if (!process.env.NODE_ENV) { process.env.NODE_ENV = "cypress" } process.env.ENABLE_ANALYTICS = "0" -process.env.JWT_SECRET = cypressConfig.env.JWT_SECRET +process.env.JWT_SECRET = testConfig.env.JWT_SECRET process.env.SELF_HOSTED = 1 process.env.WORKER_URL = `http://localhost:${WORKER_PORT}/` process.env.APPS_URL = `http://localhost:${SERVER_PORT}/` @@ -23,10 +23,7 @@ process.env.ALLOW_DEV_AUTOMATIONS = 1 // Stop info logs polluting test outputs process.env.LOG_LEVEL = "error" -exports.run = ( - serverLoc = "../../server/dist", - workerLoc = "../../worker/dist" -) => { +exports.run = (serverLoc = "../server/dist", workerLoc = "../worker/dist") => { // require("dotenv").config({ path: resolve(dir, ".env") }) // don't make this a variable or top level require // it will cause environment module to be loaded prematurely diff --git a/packages/builder/src/App.svelte b/packages/builder/src/App.svelte index 4d193df104..f31f45bb84 100644 --- a/packages/builder/src/App.svelte +++ b/packages/builder/src/App.svelte @@ -3,7 +3,6 @@ import { routes } from "../.routify/routes" import { NotificationDisplay, BannerDisplay } from "@budibase/bbui" import { parse, stringify } from "qs" - import HelpIcon from "components/common/HelpIcon.svelte" import LicensingOverlays from "components/portal/licensing/LicensingOverlays.svelte" const queryHandler = { parse, stringify } @@ -11,14 +10,10 @@